WPF之复选MVVMTreeView(TreeView+CheckBox)

博客 分享
0 349
张三
张三 2022-02-18 14:55:30
悬赏:0 积分 收藏

WPF之复选MVVM TreeView(TreeView+CheckBox)

需求背景:

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

实现方式:

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

1、创建模型 CheckModel

 1 /// <summary> 2     /// 模型可进行序列化 3     /// </summary> 4     [Serializable] 5     public class CheckModel : BindableBase 6     { 7         public CheckModel() 8         { 9 10         }11         private bool? _IsSelected=false;12         public bool? IsSelected13         {14             get { return _IsSelected; }15             set {16                 if (SetProperty(ref _IsSelected, value))17                 {18                     SelectCheck(value, true, true);19                 }20             }21         }22         /// <summary>23         /// 设置全选状态24         /// </summary>25         /// <param name="value"></param>26         /// <param name="checkedChildren"></param>27         /// <param name="checkedParent"></param>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         /// <summary>40         /// 设置父类选中状态41         /// </summary>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 Title65         {66             get { return _Title; }67             set { SetProperty(ref _Title, value); }68         }69         /// <summary>70         /// 这一点很关键,解决Json序列化循环依赖问题71         /// </summary>72         [JsonIgnore]73         private CheckModel _Parent;74         [JsonIgnore]75         public CheckModel Parent76         {77             get { return _Parent; }78             set { SetProperty(ref _Parent, value); }79         }80         private ObservableCollection<CheckModel> _ChildList=new ObservableCollection<CheckModel>();81         public ObservableCollection<CheckModel> ChildList82         {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<CheckModel>(); 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<CheckModel> _ListData = new ObservableCollection<CheckModel>()23         {24 25         };26         public ObservableCollection<CheckModel> ListData27         {28             get { return _ListData; }29             set { SetProperty(ref _ListData, value); }30         }31         private ObservableCollection<CheckModel> _CheckListData = new ObservableCollection<CheckModel>();32         public ObservableCollection<CheckModel> CheckListData33         {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<CheckModel> list = Newtonsoft.Json.JsonConvert.DeserializeObject<ObservableCollection<CheckModel>>(datas);47             CheckListData = new ObservableCollection<CheckModel>(GetCheckedItems(list));48             #endregion49             //#region 还原上面描述场景50             //CheckListData = new ObservableCollection<CheckModel>(GetCheckedItems(ListData));51             //#endregion52         }53         /// <summary>54         /// 获取选中项55         /// </summary>56         /// <param name="tree">需要递归的集合</param>57         private ObservableCollection<CheckModel> GetCheckedItems(ObservableCollection<CheckModel> tree)58         {59             //用于存储抓取的选中临时数据60             ObservableCollection<CheckModel> list = new ObservableCollection<CheckModel>();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

posted @ 2022-02-18 14:47 害羞的青蛙 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员