gpt4 book ai didi

c# - 使用带有 HierarchicalDatatemplate 的附加行为

转载 作者:行者123 更新时间:2023-12-03 10:42:39 24 4
gpt4 key购买 nike

目前我正在尝试在 TreeView 中显示自定义类的 ObservableCollection,当用户双击“项目”时,它将触发 ViewModel 中的一个方法,将选定的自定义类作为参数传递。我正在为我的 WPF 应用程序使用 MVVM 结构。

我面临的问题是 Observable Collection 使用 HierarchicalDataTemplate 显示。查看 TreeView 的整个 XAML 代码下方

<TreeView Name="DeviceTreeView" ItemsSource="{Binding ViewableTIADeviceTree}" Grid.Column="3" Margin="5">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type treeviewable:ViewableTIADevice}" ItemsSource="{Binding DeviceItems}">
<TextBlock Text="{Binding Path=DeviceName}"/>

<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type treeviewable:ViewableTIADevice}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command"
Value="{Binding TIADeviceTreeItemDoubleClick}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter"
Value="{Binding}"/>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type treeviewable:ViewableDeviceItem}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>

和 MouseDoubleClick 附加的行为类:
public class MouseDoubleClick
{
public static DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command",
typeof(ICommand),
typeof(MouseDoubleClick),
new UIPropertyMetadata(CommandChanged));

public static DependencyProperty CommandParameterProperty =
DependencyProperty.RegisterAttached("CommandParameter",
typeof(object),
typeof(MouseDoubleClick),
new UIPropertyMetadata(null));

public static void SetCommand(DependencyObject target, ICommand value)
{
target.SetValue(CommandProperty, value);
}

public static void SetCommandParameter(DependencyObject target, object value)
{
target.SetValue(CommandParameterProperty, value);
}

public static object GetCommandParameter(DependencyObject target)
{
return target.GetValue(CommandParameterProperty);
}

public static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
Control control = target as Control;

if(control != null)
{
if((args.NewValue != null) && (args.OldValue == null))
{
control.MouseDoubleClick += OnMouseDoubleClick;
}
else if((args.NewValue == null) && (args.OldValue != null))
{
control.MouseDoubleClick -= OnMouseDoubleClick;
}
}
}

private static void OnMouseDoubleClick(object sender, RoutedEventArgs e)
{
Control control = sender as Control;
ICommand command = (ICommand)control.GetValue(CommandProperty);

object commandParameter = control.GetValue(CommandParameterProperty);
command.Execute(commandParameter);
}

}

我面临的问题是它说“ViewableTIADevice”不是 FrameWorkElement,因此我什至无法运行它。

我也尝试过使用
<Style TargetType"{x:Type TreeViewItem}">

确实可以运行,但是在尝试双击 TreeView 中的项目时我没有得到任何响应。

我已经搜索了很多解决方案,我想引用这个帖子: WPF/MVVM - how to handle double-click on TreeViewItems in the ViewModel?

我一直在使用上述线程作为解决方案,但是如何将该解决方案与 HierarchicalDatatemplate 结合使用?

编辑

我试图通过双击一个项目来调用的 ICommand
 public RelayCommand TIADeviceTreeItemDoubleClick { get; set; }

我在这里将其分配给函数的位置
 TIADeviceTreeItemDoubleClick = new RelayCommand(c => tiaDeviceTreeItemDoubleClick(c));

以及它所指的功能:
 private void tiaDeviceTreeItemDoubleClick(object value)
{
//code
}

这是 ViewableTIADevice 类:
public class ViewableTIADevice
{
public ViewableTIADevice()
{
DeviceItems = new List<ViewableDeviceItem>();
}
public string DeviceName { get; set; }

public IList<ViewableDeviceItem> DeviceItems { get; set; }
}

最佳答案

我相信您对您的数据上下文有误解,请考虑以下示例:

<TreeView ItemsSource="{Binding Items}">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ItemProperty1}"></TextBlock>
</DataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Local:MouseDoubleClick.Command"
Value="{Binding ElementName=DeviceTreeView, Path=DataContext.TIADeviceTreeItemDoubleClick}"/>
<Setter Property="Local:MouseDoubleClick.CommandParameter"
Value="{Binding}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>

我的 TreeView 的数据上下文是我的 View 模型,所以当我说 ItemsSource="{Binding Items}"时,我正在绑定(bind)到我的 ViewModel 中名为 Items 的可观察集合。

TreeView.ItemTemplate 中的数据上下文是集合项中的一项。这意味着当我说 {Binding ItemProperty1} 时,我正在绑定(bind)的不是 ViewModel.ItemProprty1,而是集合 ViewModel.Items 中的单个项目。这意味着你必须有一个 ViewModel,并且在一个名为 Items 的集合中,在这个集合中你需要有 X 类型的对象,并且 X 类必须有一个名为 ItemProperty1 的属性。

TreeView.ItemContainerStyle 中的数据上下文也是集合 Items 中的一个项目,这意味着当您说 {Binding TIADeviceTreeItemDoubleClick} 时,您正在尝试绑定(bind)到集合 Items 内的类内部的 ICommand 属性。您的数据上下文不是您假设的 ViewModel,而是 ViewModel.Items 中的一个项目

所以当你使用这个时:
Value="{Binding ElementName=DeviceTreeView, Path=DataContext.TIADeviceTreeItemDoubleClick}"

您正在绑定(bind)到 TreeView 的数据上下文,即 ViewModel,它包含一个名为 TIADeviceTreeItemDoubleClick 的 ICommand 属性。

当你写这个:
{Binding TIADeviceTreeItemDoubleClick}

您正在尝试绑定(bind)到当前 TreeViewItem 的数据上下文,这是您的集合项中的一个对象。所以这只有在你将 ICommand 添加到你的集合项目中的类时才有效。

你也用这个:
<Setter Property="Local:MouseDoubleClick.CommandParameter"
Value="{Binding}"

在这里,显然,您在集合 Items 中发送一个项目,而不是 ViewModel。

有道理?

关于c# - 使用带有 HierarchicalDatatemplate 的附加行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48807963/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com