需求背景:

当我们用到权限菜单栏时权限菜单栏属于递归效果,我们需要用到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. centos 操作系统优化

    命令提示符优化 修改PS1环境变化 vim /etc/profile #在最后一行添加 export PS1='[\u@\H \w]$' \u ---显示当前登录用户名称 \h ---显示系统主机名称 ...

  2. Jarvis OJ--PHPINFO

    一道浙大的题目 题目地址:http://web.jarvisoj.com:32784 拿到这道题目, 是一道反序列化的题目,题目源码很简单,当创建OowoO()这个类的对象时,会自动调用__const ...

  3. Java库中的LocalDate类

    Java库中的LocalDate类 类库设计者决定将保存时间与给时间点命名分开.所以标准Java类库分别包含了两个类:一个用来表示时间点的Date类:另一个是用来表示大家熟悉的日历表示法的LocalD ...

  4. Nginx 反向代理解决跨域问题分析

    当你遇到跨域问题,不要立刻就选择复制去尝试.请详细看完这篇文章再处理 .我相信它能帮到你. 分析前准备: 前端网站地址:http://localhost:8080 服务端网址:http://local ...

  5. 【记录一个问题】go get -u github.com/go-redis/redis出现错误" invalid character '.' after top-level value"

    安装某个库的时候依赖于redis库,总是出现这样的错误: go install go: github.com/go-redis/redis/v7@v7.2.0: parsing go.mod: mis ...

  6. 洛谷P1002过河卒java100分题解

    题目描述如图: 这道题我以前以回溯的方法做,只能拿到60分 现在才发现是道动态规划题 解题思路: 创建一个(0,0)到终点打小的二维数组表示棋盘 每个坐标的值为此位置到终点的路数 最下方一排和最右方一 ...

  7. tcp|ip nagle算法

    在TCP传输数据流中,存在两种类型的TCP报文段,一种包含成块数据(通常是满长度的,携带一个报文段最多容纳的字节数),另一种则包含交互数据(通常只有携带几个字节数据). 对于成块数据的报文段,TCP采 ...

  8. Javascript之递归求裴波那契数

    一.遍历的方式性能更加,递归的方式代码利于阅读.简短,性能略差 二.裴波那契数定义: · 位置0的裴波那契数为0 · 1和2的裴波那契数为1 · n(n > 2)裴波那契数为 (n-1)的裴波那 ...

  9. Lesson3——Pandas Series结构

    1 什么是Series结构? Series 结构,也称 Series 序列,是 Pandas 常用的数据结构之一,它是一种类似于一维数组的结构,由一组数据值(value)和一组标签组成,其中标签与数据 ...

  10. c#代码设计:子类和父类

    哭辽,事情是这样的 我想写个产品类用来放点相机参数,想类似这种的使用方式:(时间关系不改了,产品=Zoo,animals=相机) Zoo Zooxx= new Zoo (); Zoo.Animals ...