WPF TreeView 检测SelectedItem变化的简单方案

  • WPF TreeView 检测SelectedItem变化的简单方案已关闭评论
  • 108 次浏览
  • A+
所属分类:.NET技术
摘要

TreeView无法绑定SelectedItem,而又想知道treeview的selecteditem的变化,当然目前有很多方法,我这里简单的提供一个。

TreeView无法绑定SelectedItem,而又想知道treeview的selecteditem的变化,当然目前有很多方法,我这里简单的提供一个。

目前主要思路就是通过处理xaml的TreeViewItem的IsSelected属性来进行绑定。

  <TreeView             BorderThickness="0"             Width="220"             ItemsSource="{Binding Items, IsAsync=True}"             HorizontalAlignment="Left">             <TreeView.ItemContainerStyle>                 <Style TargetType="{x:Type TreeViewItem}">                     <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />                     <Setter Property="FontWeight" Value="Normal" />                     <Setter Property="HorizontalAlignment" Value="Left" />                     <Style.Triggers>                         <Trigger Property="IsSelected" Value="True">                             <Setter Property="FontWeight" Value="Bold" />                         </Trigger>                     </Style.Triggers>                 </Style>             </TreeView.ItemContainerStyle>             <TreeView.ItemTemplate>                 <HierarchicalDataTemplate ItemsSource="{Binding Items, IsAsync=True}">                     <Label Content="{Binding Name}" />                 </HierarchicalDataTemplate>             </TreeView.ItemTemplate>         </TreeView>

主要部分是

   <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

这里的意思就是绑定到集合泛型的IsSelected属性。

这里呢主要是通过抽象类去实现的也就是:

 public abstract class TreeViewItemModel<T> : Notify     {          private bool _IsSelected;          public bool IsSelected         {             get { return _IsSelected; }             set             {                 _IsSelected = value;                 OnChanged();                 if (value)                 {                     IChanged<T> changed = ModelChangedManger.Sub.Get<T>();                     if (changed?.Accepted == true)                     {                         changed.OnModelChanged((T)Convert.ChangeType(this, typeof(T)));                     }                 }              }         }     }

具体的使用类再去继承即可,也就是

public class GroupModel : TreeViewItemModel<GroupModel>     {         public GroupModel()         {             Id = Guid.NewGuid();         }         private Guid _id;          public Guid Id         {             get { return _id; }             set             {                 _id = value;                 OnChanged();             }         }         private string _name;          public string Name         {             get { return _name; }             set             {                 _name = value;                 OnChanged();             }         }         private ObservableCollection<GroupModel> _Item = new ObservableCollection<GroupModel>();         public ObservableCollection<GroupModel> Items         {             get { return _Item; }             set             {                 _Item = value;                 OnChanged();             }         }      }

处理完这样,我们只是完成了一部分。这里这来说下

          if (value)                 {                     IChanged<T> changed = ModelChangedManger.Sub.Get<T>();                     if (changed?.Accepted == true)                     {                         changed.OnModelChanged((T)Convert.ChangeType(this, typeof(T)));                     }                 }

这个是干什么的。

很明显,Isslected属性触发,我们想通知viewmodel,treeview的selecteditem属性变了,或者叫做selectindex也变了的意思。所以简单的实现了一个事件聚合器,这个部分代码比较简单,整体如下

    public interface IChanged<T>     {         void OnModelChanged(T Model);         bool Accepted { get; set; }     }      public sealed class ModelChangedManger     {         private ModelChangedManger()         {          }         static ModelChangedManger() { }         private class Inner         {             private Inner() { }             internal readonly static ModelChangedManger manger = new ModelChangedManger();         }         private ConcurrentDictionary<Type, object> Keys { get; set; } = new ConcurrentDictionary<Type, object>();         public IChanged<T> Get<T>()         {             if (Keys.TryGetValue(typeof(T), out object val))             {                 return val as IChanged<T>;             }             return null;         }         public void Set<T>(IChanged<T> model)         {             if (!Keys.ContainsKey(typeof(T)))             {                 Keys.TryAdd(typeof(T), model);             }         }         public void Remove<T>()         {             Keys.TryRemove(typeof(T), out _);         }         public static ModelChangedManger Sub         {             get => Inner.manger;         }     }

主要是Ichanged接口和manger的一起搭配使用。使用字典将要引发和被引发的类型,类存储起来,这样就可以全局或者大范围的使用了。

同理 我们需要viewmodel上继承一个引发事件的ichanged类

  public abstract class TreeViewModel<T> : Notify, IChanged<T>     {         public virtual void OnModelChanged(T Model)         {             SelectedItem = Model;         }          private bool _Accepted;          public bool Accepted         {             get { return _Accepted; }             set             {                 _Accepted = value;                 OnChanged();             }         }          private T _SelectedItem;          public T SelectedItem         {             get { return _SelectedItem; }             set             {                 _SelectedItem = value;                 OnChanged();             }         }     }      public class ViewModel : TreeViewModel<GroupModel>     {         private System.Collections.ObjectModel.ObservableCollection<GroupModel> _list = new System.Collections.ObjectModel.ObservableCollection<GroupModel>();          public System.Collections.ObjectModel.ObservableCollection<GroupModel> Items         {             get { return _list; }             set             {                 _list = value;                 OnChanged();             }         }         public ViewModel()         {             GroupModel groupModel1 = new GroupModel();             groupModel1.Name = "Ken";              GroupModel groupModel_1 = new GroupModel();             groupModel_1.Name = "A";             GroupModel groupModel_2 = new GroupModel();             groupModel_2.Name = "B";             GroupModel groupModel_3 = new GroupModel();             groupModel_3.Name = "C";             GroupModel groupModel_4 = new GroupModel();             groupModel_4.Name = "D";              groupModel1.Items.Add(groupModel_1);             groupModel1.Items.Add(groupModel_2);             groupModel1.Items.Add(groupModel_3);             groupModel1.Items.Add(groupModel_4);               GroupModel groupModel2 = new GroupModel();             groupModel2.Name = "TOM";              GroupModel groupModel_5 = new GroupModel();             groupModel_5.Name = "a";             GroupModel groupModel_6 = new GroupModel();             groupModel_6.Name = "b";             GroupModel groupModel_7 = new GroupModel();             groupModel_7.Name = "c";             GroupModel groupModel_8 = new GroupModel();             groupModel_8.Name = "d";              groupModel2.Items.Add(groupModel_5);             groupModel2.Items.Add(groupModel_6);             groupModel2.Items.Add(groupModel_7);             groupModel2.Items.Add(groupModel_8);              Items.Add(groupModel1);             Items.Add(groupModel2);             ModelChangedManger.Sub.Set(this);             this.Accepted = true;         }     }

这样,就可以简单的实现了对selectedItem的变化的监控了

源代码连接