需求背景:

当我们用到权限菜单栏时权限菜单栏属于递归效果,我们需要用到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? IsSelected
13 {
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 Title
65 {
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 Parent
76 {
77 get { return _Parent; }
78 set { SetProperty(ref _Parent, value); }
79 }
80 private ObservableCollection<CheckModel> _ChildList=new ObservableCollection<CheckModel>();
81 public ObservableCollection<CheckModel> 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<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> ListData
27 {
28 get { return _ListData; }
29 set { SetProperty(ref _ListData, value); }
30 }
31 private ObservableCollection<CheckModel> _CheckListData = new ObservableCollection<CheckModel>();
32 public ObservableCollection<CheckModel> 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<CheckModel> list = Newtonsoft.Json.JsonConvert.DeserializeObject<ObservableCollection<CheckModel>>(datas);
47 CheckListData = new ObservableCollection<CheckModel>(GetCheckedItems(list));
48 #endregion
49 //#region 还原上面描述场景
50 //CheckListData = new ObservableCollection<CheckModel>(GetCheckedItems(ListData));
51 //#endregion
52 }
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

WPF之复选MVVM TreeView(TreeView+CheckBox)的更多相关文章

  1. 关于复选框input[type=checkbox]

    关于复选框input[type=checkbox],其实在前面的文章中说过一次,当时主要关注点在设置复选框的状态,利用prop实现,今天继续关注一下复选框. 自己在项目中,遇到一个全选/全不选的需求, ...

  2. js做全选,用一个checkbox复选框做多个checkbox复选框的全选按钮,有一个复选框未被选择时,全选按钮的checked就为false

    用一个checkbox复选框做多个checkbox复选框的全选按钮,有一个复选框未被选择时,全选按钮的checked就为false,当所有checkbox都被选中时,全选按钮也被选中. 详解: 有两种 ...

  3. WPF:带复选框CheckBox的树TreeView

    最近要用WPF写一个树,同事给了我一个Demo(不知道是从哪里找来的),我基本上就是参照了这个Demo. 先放一下效果图(3棵树): 这个树索要满足的条件是: 父节点.Checked=true时,子节 ...

  4. 实现带复选框的TreeView控件

    实现效果: 知识运用: TreeView控件的CheckView属性 //是否在树形视图控件中显示复选框 public bool CheckBoxs{ get;ser } 实现代码: TreeView ...

  5. 表单复选框input[type="checkbox"]

    <!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...

  6. pentaho cde 自定义复选下拉框 checkbox select

    pentaho  自带的component 虽多,但是当用户需要在一个表格中查看多个组别的数据时,pentaho自带的单选框就不能实现了,所以复选下拉框势在必行,实现效果如下: 实现原理是借用了jqu ...

  7. 复选框(checkbox)、单选框(radiobox)的使用

    复选框(checkbox).单选框(radiobox)的使用 复选框: HTML: // 复选框 <input type="checkbox" name="chec ...

  8. Selenium2+python自动化19-单选框和复选框(radiobox、checkbox)

    本篇主要介绍单选框和复选框的操作 一.认识单选框和复选框 1.先认清楚单选框和复选框长什么样 2.各位小伙伴看清楚哦,上面的单选框是圆的:下图复选框是方的,这个是业界的标准,要是开发小伙伴把图标弄错了 ...

  9. firefox中 checkbox属性checked="checked"已有,但复选框却不显示打钩的原因

    最近在调试复选框的应用,在ie没有问题,考虑到兼容性,试试了firefox,遇到了问题. 复选框绑定了click事件,点一次选中,再点击取消选中,依次类推.这个功能在ie中没问题,但是在firefox ...

随机推荐

  1. 新建koa2项目

    1.npm install -g koa-generator 2.koa2 项目名称,如果需要ejs引擎koa2 -e 项目名称 3.cd 项目名称 4.npm install 5.npm insta ...

  2. Java手动创建Web项目

    原文链接:https://www.toutiao.com/i6495693288043971086/ 为了便于理解Web项目结构,我们手动创建整个过程. 先启动Tomcat 下载Tomcat7.0 解 ...

  3. python+selenium 定位元素的主要方法

    selenium对web各元素的操作首先就要先定位元素,定位元素的方法主要有以下几种: 通过id定位元素:find_element_by_id("id_vaule") 通过name ...

  4. kafka学习笔记(六)kafka的controller模块

    概述 今天我们主要看一下kafka的controller的代码,controller代码是kafka的非常重要的代码,需要我们深入学习.从某种意义上来说,它是kafka最核心的组件,一方面,他要为集群 ...

  5. boot项目启动成功 接口全部404

    今天开发的时候遇到一个404的错误,路径启动类位置都对,就是404很气人.记录下解决的过程,以供遇到同等困惑的小伙伴参考 404原因排查步骤 首先按照下面步骤检查一遍 首先检查路径是否正确,把路径重新 ...

  6. 【Java】数组

    文章目录 数组 一.数组的定义 二.数组的声明与创建 三.内存分析 四.三种初始化 五.数组的四个基本特点 六.数组边界 七.数组的使用 八.多维数组 九.Arrays类 十.稀疏数组 数组 一.数组 ...

  7. MySQL 5.7 版本的 UTF8 字符集调研

    一.故事背景 记一次 sql_mode 非严格模式下的业务事故排查.当时数据库没有开启 sql_mode 为严格模式,并且数据表的编码是 utf8,表现为业务侧的 Insert SQL 语句执行成功, ...

  8. 用Cesium可视化地下设施、矿山和地质层

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 本月的CesiumJS 1.70发布引入的一项关键改进是地下数据 ...

  9. pytest文档3-测试用例setup和teardown

    用例运行级别 模块级(setup_module/teardown_module)开始于模块始末,全局的 函数级(setup_function/teardown_function)只对函数用例生效(不在 ...

  10. 使用Outlook欺骗性云附件进行网络钓鱼

    滥用Microsoft365 Outlook 云附件的方式发送恶意文件,使恶意可执行云附件规避云查杀检测 介绍 在本文中,我们将探讨如何滥用 O365 上的云附件功能使可执行文件(或任何其他文件类型) ...