WPF MVVM:从ListView中选择TreeViewItem

时间:2014-06-17 05:50:26

标签: c# wpf xaml listview mvvm

我有一个基于MVVM软件架构的wpf应用程序。它由treeView和ListView组成。单击treeView节点时,该节点的所有子节点都将显示在列表视图中。我能够实现这一部分。

但是当用户单击listView中的某个项目时,应该在treeView中选择该特定项目(树视图中的节点)。我不知道该怎么做。 基本上我想将属性SelectedItem绑定到listview所选项。但看起来像treeview selectedItem propeerty是readonly。

    <TreeView Name="tv" ItemsSource="{Binding ChildAndAttributes}" VerticalAlignment="Stretch" Margin="12,12,12,35">
        <TreeView.Resources>
            <DataTemplate DataType="{x:Type tvcc:NodeViewModel}">
                <TextBlock Text="{Binding Text}" />
            </DataTemplate>
            <DataTemplate DataType="{x:Type tvcc:NodeAttributeViewModel}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding AttributeName}"  />
                    <TextBlock Text="{Binding AttributeValue}" Padding="2,0,0,0" Foreground="Blue" />
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding ChildAndAttributes}">
                <ContentControl Content="{Binding}" />
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

2 个答案:

答案 0 :(得分:0)

以下是树https://stackoverflow.com/a/18265571/634219的一些扩展,它允许您绑定树的选定项:

public class TreeViewEx : TreeView
{
    public TreeViewEx()
    {
        SelectedItemChanged += TreeViewEx_SelectedItemChanged;
    }

    void TreeViewEx_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        SelectedItem = e.NewValue;
    }

    #region SelectedItem

    /// <summary>
    /// Gets or Sets the SelectedItem possible Value of the TreeViewItem object.
    /// </summary>
    public new object SelectedItem
    {
        get { return GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(TreeViewEx), new PropertyMetadata(SelectedItemProperty_Changed));

    static void SelectedItemProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var targetObject = dependencyObject as TreeViewEx;
        if (targetObject != null)
        {
            var tvi = targetObject.FindItemNode(targetObject.SelectedItem);
            if (tvi != null)
                tvi.IsSelected = true;
        }
    }
    #endregion SelectedItem

    public TreeViewItem FindItemNode(object item)
    {
        TreeViewItem node = null;
        foreach (object data in Items)
        {
            node = ItemContainerGenerator.ContainerFromItem(data) as TreeViewItem;
            if (node != null)
            {
                if (data == item)
                    break;
                node = FindItemNodeInChildren(node, item);
                if (node != null)
                    break;
            }
        }
        return node;
    }

    protected TreeViewItem FindItemNodeInChildren(TreeViewItem parent, object item)
    {
        TreeViewItem node = null;
        bool isExpanded = parent.IsExpanded;
        if (!isExpanded) //Can't find child container unless the parent node is Expanded once
        {
            parent.IsExpanded = true;
            parent.UpdateLayout();
        }
        foreach (object data in parent.Items)
        {
            node = parent.ItemContainerGenerator.ContainerFromItem(data) as TreeViewItem;
            if (data == item && node != null)
                break;
            node = FindItemNodeInChildren(node, item);
            if (node != null)
                break;
        }
        if (node == null && parent.IsExpanded != isExpanded)
            parent.IsExpanded = isExpanded;
        if (node != null)
            parent.IsExpanded = true;
        return node;
    }
} 

答案 1 :(得分:0)

TreeViewItem中选择TreeView的最简单方法之一是将数据绑定到TreeViewItem.IsSelected Property。这个 意味着您必须向数据类型类添加额外的bool IsSelected属性,但它将允许您从视图模型中选择任何项目。您可以在Style

中绑定到此属性的数据
<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>

或者,您可能还希望将数据绑定到TreeViewItem.IsExpanded Property,以便您可以从视图模型中选择展开相关项:

YourDataType item = Items.First(i => i.Id == someValue);
item.IsSelected = true;
item.IsExpanded = true;