需求背景:
当我们用到权限菜单栏时权限菜单栏属于递归效果,我们需要用到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