WPF MVVM:从列表视图中选择treeviewem
本文关键字:选择 treeviewem 视图 列表 MVVM WPF | 更新日期: 2023-09-27 18:08:59
我有一个基于MVVM软件架构的wpf应用程序。它由treeView和ListView组成。当单击一个treeView节点时,该节点的所有子节点都显示在列表视图中。我能够做到这一点。
但是当用户点击listView中的一个项目时,这个特定的项目(它是treeview中的一个节点)应该在treeview中被选中。我不知道该怎么做。基本上我想绑定属性SelectedItem到listview selected item。但是好像treeview的selectedItem属性是只读的
<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>
下面是tree https://stackoverflow.com/a/18265571/634219的一些扩展,允许您绑定树的selecteditem:
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;
}
}
在TreeView
中选择TreeViewItem
的最简单方法之一是将数据绑定到TreeViewItem.IsSelected
属性。这个确实意味着您必须向数据类型类添加一个额外的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
属性,以便您可以选择和从视图模型展开相关项:
YourDataType item = Items.First(i => i.Id == someValue);
item.IsSelected = true;
item.IsExpanded = true;