WPF之复选MVVM TreeView(TreeView+CheckBox)

需求背景:

当我们用到权限菜单栏时权限菜单栏属于递归效果,我们需要用到TreeView+CheckBox进行组合复选开发时,我们需要解决此类问题时怎么办,那么就引出今天的小笔记内容

实现方式:

下载MVVM框架以及Newtonsoft,这时候可能大家会觉得奇怪,为什么还会用到Json,大家直接看代码,我每一步骤都很详细,代码可直接粘贴,让大家爽一爽

1、创建模型 CheckModel

 1 /// 
 2     /// 模型可进行序列化
 3     /// 
 4     [Serializable]
 5     public class CheckModel : BindableBase
 6     {
 7         public CheckModel()
 8         {
 9 
10         }
11         private bool? _IsSelected=false;
12         public bool? IsSelected
13         {
14             get { return _IsSelected; }
15             set {
16                 if (SetProperty(ref _IsSelected, value))
17                 {
18                     SelectCheck(value, true, true);
19                 }
20             }
21         }
22         /// 
23         /// 设置全选状态
24         /// 
25         /// 
26         /// 
27         /// 
28         private void SelectCheck(bool? value, bool checkedChildren, bool checkedParent)
29         {
30             if (checkedChildren && value.HasValue && ChildList != null)
31                 foreach (var item in ChildList)
32                 {
33                     item.SelectCheck(value, true, false);
34                 }
35             if (checkedParent && this.Parent != null)//父类模型不为空就进行状态修改
36                 this.Parent.CheckParentCheckState();
37             IsSelected = value;
38         }
39         /// 
40         /// 设置父类选中状态
41         /// 
42         private void CheckParentCheckState()
43         {
44             bool? _currentState = this._IsSelected;//临时存储当前选中状态
45             bool? _firstState = null;//刚开始预设为选中状态为空
46 
47             for (int i = 0; i < this.ChildList.Count(); i++)
48             {
49                 bool? childrenState = this.ChildList[i].IsSelected;//抓起子集合选中状态
50                 if (i == 0)//如果为第一次循环,将子集选中状态赋给预设状态
51                 {
52                     _firstState = childrenState;
53                 }
54                 else if (_firstState != childrenState)//如果不是第一次循环将预设状态,也就是将父类选中站台标记为空(空代表子集又被选中)
55                 {
56                     _firstState = null;
57                 }
58             }
59             if (_firstState != null) _currentState = _firstState;//如果预设的状态不为空,将预设状态给临时存储当前选中状态
60             SelectCheck(_firstState, false, true);//开始设置选中状态
61         }
62 
63         private string _Title;
64         public string Title
65         {
66             get { return _Title; }
67             set { SetProperty(ref _Title, value); }
68         }
69         /// 
70         /// 这一点很关键,解决Json序列化循环依赖问题
71         /// 
72         [JsonIgnore]
73         private CheckModel _Parent;
74         [JsonIgnore]
75         public CheckModel Parent
76         {
77             get { return _Parent; }
78             set { SetProperty(ref _Parent, value); }
79         }
80         private ObservableCollection _ChildList=new ObservableCollection();
81         public ObservableCollection ChildList
82         {
83             get { return _ChildList; }
84             set { SetProperty(ref _ChildList, value); }
85         }
86     }

2、创建ViewModel

 1 public class MainWindowViewModel : BindableBase
 2     {
 3         public MainWindowViewModel()
 4         {
 5             CheckModel model = new CheckModel();
 6             model.Title = "目录";
 7             model.ChildList = new ObservableCollection();
 8             ListData.Add(model);
 9                 CheckModel chmodel = new CheckModel();
10                 chmodel.Title = "目录1";
11                 chmodel.Parent = model; 
12                     CheckModel chmodel_1 = new CheckModel();
13                     chmodel_1.Title = "目录1-1";
14                     chmodel_1.Parent = chmodel;
15                     chmodel.ChildList.Add(chmodel_1);
16                 model.ChildList.Add(chmodel);
17                 CheckModel chmodel2 = new CheckModel();
18                 chmodel2.Title = "目录2";
19                 chmodel2.Parent = model;
20                 model.ChildList.Add(chmodel2);
21         }
22         private ObservableCollection _ListData = new ObservableCollection()
23         {
24 
25         };
26         public ObservableCollection ListData
27         {
28             get { return _ListData; }
29             set { SetProperty(ref _ListData, value); }
30         }
31         private ObservableCollection _CheckListData = new ObservableCollection();
32         public ObservableCollection CheckListData
33         {
34             get { return _CheckListData; }
35             set { SetProperty(ref _CheckListData, value); }
36         }
37         private DelegateCommand _CheckedCommand;
38         public DelegateCommand CheckedCommand =>
39             _CheckedCommand ?? (_CheckedCommand = new DelegateCommand(ExecuteCheckedCommand));
40 
41         void ExecuteCheckedCommand()
42         {
43             CheckListData.Clear();
44             #region 这一点很重要,用过Json解决集合地址引用问题,如果直接进行原有集合抓取选中状态,那么你进行递归筛查时涉及到数据地址引用问题,造成源数据被破环问题,利用Json序列化字符串就可以完美就解决地址引用问题
45             string datas = Newtonsoft.Json.JsonConvert.SerializeObject(ListData.ToList());
46             ObservableCollection list = Newtonsoft.Json.JsonConvert.DeserializeObject>(datas);
47             CheckListData = new ObservableCollection(GetCheckedItems(list));
48             #endregion
49             //#region 还原上面描述场景
50             //CheckListData = new ObservableCollection(GetCheckedItems(ListData));
51             //#endregion
52         }
53         /// 
54         /// 获取选中项
55         /// 
56         /// 需要递归的集合
57         private ObservableCollection GetCheckedItems(ObservableCollection tree)
58         {
59             //用于存储抓取的选中临时数据
60             ObservableCollection list = new ObservableCollection();
61             if (tree.ToList().Count > 0)
62             {
63                 foreach (var item in tree)
64                 {
65                     //检测选中状态
66                     if (item.IsSelected != false) {
67                         //防呆,检测集合空值。若为空值 直接进行添加当前对象
68                         if (item.ChildList!=null)
69                         {
70                             //很重要->>>递归抓取下一层集合数据赋予当前模型集合
71                             item.ChildList = GetCheckedItems(item.ChildList);
72                             //填充当前抓取的对象
73                             list.Add(item);
74                         }
75                         else {
76                             /// 填充当前抓取的对象
77                             list.Add(item);
78                         }
79                     }
80                 }
81             }
82             return list;
83         }
84     }

备注:

  原创文章禁止转载 2022-02-18

你可能感兴趣的:(WPF之复选MVVM TreeView(TreeView+CheckBox))