【问题标题】:Using attachedbehaviors with an HierarchicalDatatemplate使用带有 HierarchicalDatatemplate 的附加行为
【发布时间】:2018-02-15 13:02:14
【问题描述】:

目前我正在尝试在 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; }
}

【问题讨论】:

  • 告诉我们你在哪里定义 ICommand“TIADeviceTreeItemDoubleClick”,因为我担心你没有在你的集合 DeviceItems 中的类中定义它
  • 好吧,然后尝试像这样设置命令:Value="{Binding ElementName=DeviceTreeView, Path=DataContext.TIADeviceTreeItemDoubleClick}"
  • 这不起作用,一直抛出的异常是'配置 System.Windows.Style.TargetType 的属性导致第 52 行位置 34 的异常' 第 52 行是:
  • ViewableTIADevice 是否派生自 TreeViewItem?再试一次“
  • 不,我没有尝试过这样做并覆盖“GetContainerForItemOverride”和“IsItemItsOwnContainerOverride”。但是树是空的。

标签: c# wpf xaml mvvm treeview


【解决方案1】:

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

<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 的数据上下文是我的视图模型,所以当我说 ItemsSource="{Binding Items}" 时,我将绑定到我的 ViewModel 中名为 Items 的可观察集合。

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

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

所以当你使用这个时:

Value="{Binding ElementName=DeviceTreeView, Path=DataContext.TIADeviceTreeItemDoubleClick}"

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

当你写这个时:

{Binding TIADeviceTreeItemDoubleClick}

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

你也用这个:

<Setter Property="Local:MouseDoubleClick.CommandParameter"
                                Value="{Binding}"

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

有意义吗?

【讨论】:

  • 啊,是的,现在确实有意义。我确实假设 ItemContainerStyle 的 Setter 的数据上下文是 ViewModel。感谢您在这么短的时间内帮助我!
猜你喜欢
  • 2014-09-27
  • 1970-01-01
  • 2013-01-31
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 1970-01-01
相关资源
最近更新 更多