MVVM处理TreeView的SelectedItem的绑定的两种方式
TreeView的SelectedItem不支持MVVM绑定:
因为它是只读的。
有时候我们就需要对它进行绑定
1.使用自定义Behavior
需要引用System.Windows.Interactivity.dll
自定义Behavior如下:
public class TreeViewBehavior : Behavior<TreeView> { public object SelectedItem { get { return (object)GetValue(SelectedItemProperty); } set { SetValue(SelectedItemProperty, value); } } // Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(TreeViewBehavior), new PropertyMetadata(null, OnSelectedItemChanged)); private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var treeViewHelper = d as TreeViewBehavior; SetItemSelected(treeViewHelper.AssociatedObject, e.NewValue); } private static void SetItemSelected(TreeView tree, object context) { for (int i = 0; i < tree.Items.Count; i++) { var treeItem = tree.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem; if (SetItemSelected(treeItem,context)) { return; } } } private static bool SetItemSelected(TreeViewItem treeViewItem,object datacontext) { if (treeViewItem.DataContext == datacontext) { treeViewItem.IsSelected = true; return true; } for (int i = 0; i < treeViewItem.Items.Count; i++) { var subTreeViewItem = treeViewItem.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem; if (subTreeViewItem != null && subTreeViewItem.DataContext == datacontext) { subTreeViewItem.IsSelected = true; return true; } } return false; } protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.SelectedItemChanged += AssociatedObject_Selected; } private void AssociatedObject_Selected(object sender, System.Windows.RoutedEventArgs e) { var treeView = sender as TreeView; this.SelectedItem = treeView?.SelectedItem; } protected override void OnDetaching() { base.OnDetaching(); this.AssociatedObject.SelectedItemChanged -= AssociatedObject_Selected; } }
前台使用:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TreeView ItemsSource="{Binding Nodes}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <Grid> <TextBlock Text="{Binding Name}"></TextBlock> </Grid> </HierarchicalDataTemplate> </TreeView.ItemTemplate> <i:Interaction.Behaviors> <local:TreeViewBehavior SelectedItem="{Binding SelectedItem,Mode=TwoWay}"></local:TreeViewBehavior> </i:Interaction.Behaviors> </TreeView> <Label Grid.Column="1" Content="{Binding SelectedItem.Name}"></Label> <Button Grid.Column="1" Margin="100" Click="Button_Click"></Button> </Grid>
2.使用附加属性和注册类的路由事件
附加属性及类的路由事件处理逻辑如下:
class TreeViewHelper { static TreeViewHelper() { EventManager.RegisterClassHandler(typeof(TreeView), TreeView.SelectedItemChangedEvent, new RoutedEventHandler(OnSeletedItemChanged)); } public static object GetSelectedItem(DependencyObject obj) { return (object)obj.GetValue(SelectedItemProperty); } public static void SetSelectedItem(DependencyObject obj, object value) { obj.SetValue(SelectedItemProperty, value); } // Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewHelper), new PropertyMetadata(null,OnSelectedItemChanged)); private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { SetItemSelected(d as TreeView, e.NewValue); } private static void SetItemSelected(TreeView tree, object context) { for (int i = 0; i < tree.Items.Count; i++) { var treeItem = tree.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem; if (SetItemSelected(treeItem, context)) { return; } } } private static bool SetItemSelected(TreeViewItem treeViewItem, object datacontext) { if (treeViewItem.DataContext == datacontext) { treeViewItem.IsSelected = true; return true; } for (int i = 0; i < treeViewItem.Items.Count; i++) { var subTreeViewItem = treeViewItem.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem; if (subTreeViewItem != null && subTreeViewItem.DataContext == datacontext) { subTreeViewItem.IsSelected = true; return true; } } return false; } private static void OnSeletedItemChanged(object sender, RoutedEventArgs e) { var treeView = sender as TreeView; SetSelectedItem(treeView,treeView.SelectedItem); } }
前台代码:
<Window x:Class="WPF_TreeViewTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPF_TreeViewTest" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TreeView ItemsSource="{Binding Nodes}" local:TreeViewHelper.SelectedItem="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <Grid> <TextBlock Text="{Binding Name}"></TextBlock> </Grid> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> <Label Grid.Column="1" Content="{Binding SelectedItem.Name}"></Label> <Button Grid.Column="1" Margin="100" Click="Button_Click"></Button> </Grid> </Window>
————————————————
版权声明:本文为CSDN博主「lishuangquan1987」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lishuangquan1987/article/details/115305335