需求背景:

当我们用到权限菜单栏时权限菜单栏属于递归效果,我们需要用到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. idea 开启 tomcat 热部署 的 具体流程 和 使用方式

    1前言 一直以来,使用idea做web开发修改html.jsp.js文件后,必须手动重新部署tomcat,最少都有等个6 -10 秒, 甚至有时候还提示找不到某个编译文件报错,重新编译整个项目,那得等 ...

  2. vue2.0组件库

    UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...

  3. 《剑指offer》面试题45. 把数组排成最小的数

    问题描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.   示例 1: 输入: [10,2] 输出: "102" 示例 2: 输入: ...

  4. 《剑指offer》面试题61. 扑克牌中的顺子

    问题描述 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2-10为数字本身,A为1,J为11,Q为12,K为13,而大.小王为 0 ,可以看成任意数字.A 不能视为 14. 示例 ...

  5. JavaScript DOM 基础操作

    JavaScript DOM 基础操作 一.获取元素的六方式 document.getElementById('id名称') //根据id名称获取 document.getElementsByclas ...

  6. Android学习笔记2

    4,用intent在activity之间传递数据(两个Activity可能不是在一个应用程序中) (1),从MainActivity向HelloActivity传递参数123 package com. ...

  7. 分享一个学习cesiumjs的中文社区

    在cesiumjs中文社区的时间线中我写到: 2018年10月10日 注册用户数51,日uv破100 Mark截图 2018年06月22日 上线测试 2018年06月19日 获得cesiumcn.or ...

  8. 使用 fail2ban 保护 frp 服务

    背景 我们一般会使用 fail2ban 来保护暴露到公网的提供密码登录的 ssh 连接等. 但使用 frp 穿透后所有的从外网访问都会变成 127.0.0.1 进入的,原本能用 fail2ban 保护 ...

  9. Telegra.ph | 简洁的文章发布平台

    https://telegra.ph 自由 Telegraph 并不强调内容管理方这一概念,真正做到了「人人都是媒体」.通过 Telegraph 发布的文章,理论上来说不会存在删除的危险,并且由于会产 ...

  10. Kubernetes-Secret

    1. 简介 Secret 是一种包含少量敏感信息例如密码.令牌或密钥的对象. 这样的信息可能会被放在 Pod 规约中或者镜像中. 使用 Secret 意味着你不需要在应用程序代码中包含机密数据. 由于 ...