怎么让所有子节点被选中,父节点自动选中 TreeView

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么让所有子节点被选中,父节点自动选中 TreeView相关的知识,希望对你有一定的参考价值。

参考技术A //设置标志,防止死循环
bool check = false;

//节点勾选后事件,如果更改某一节点状态会自动触发,所以在后面的方法中无需递归
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)

if(check==false)
setchild(e.Node);
setparent(e.Node);
check = false;


//设置子节点状态
private void setchild(TreeNode node)

foreach (TreeNode child in node.Nodes)

child.Checked = node.Checked;

check = true;


//设置父节点状态
private void setparent(TreeNode node)

if (node.Parent != null)

//如果当前节点状态为勾选,则需要所有兄弟节点都勾选才能勾选父节点
if (node.Checked)
foreach (TreeNode brother in node.Parent.Nodes)

if (brother.Checked == false)
return;

node.Parent.Checked = node.Checked;



原理:先递归到最底层节点,由checkChild()勾选上最底层节点,然后改变check状态,再checkParent()勾选最底层的上一层节点,虽然触发勾选事件,但是check状态改变了,不能再向下勾选,只能向上递归,从而防止了死循环。

普通方式死循环原理:递归到最底层后,勾选上最底层,然后勾选最底层的上一层,但是会自动触发勾选事件,再次递归到最底层,因此造成死循环。

easyui Tree模拟级联勾选cascadeCheck,节点选择,父节点自动选中,节点取消,父节点自动取消选择,节点选择,所有子节点全部选择,节点取消,所有子节点全部取消勾选

最近项目中用到easyui tree,发现tree控件的cascadeCheck有些坑,不像miniui 的tree控件,级联勾选符合业务需求,所以就自己重新改写了onCheck事件,符合业务需求。网上百度了很多资料,都没有完全符合自己业务场景的,所以就自己动手写咯。

先说一下自己的业务需求:

1.选中节点,上级以及所有直系上级节点自动选中,所有下级子孙节点全部自动选中;

2.取消选择节点,如果兄弟节点都未选择,则上级以及所有直系上级节点自动取消选择,所有下级子孙节点全部取消选中。

这里说一下cascadeCheck属性,tree控件默认cascadeCheck=true,即级联勾选,但这个属性有些坑,当选择某个节点时,如果所有兄弟节点没全部选中,父节点是个方形的,不是勾选,换成勾选,也会有问题。所以索性不用这个cascadeCheck,自己模拟写一个方法。

再说一下tree自定义方法扩展:

1
2
3
4
5
6
7
8
9
$.extend($.fn.tree.methods, {
        getLeafChildren: function (jq, params) {
            var nodes = [];
            $(params).next().children().children("div.tree-node").each(function () {
                nodes.push($(jq[0]).tree(‘getNode‘this));
            });
            return nodes;
        }
    });

这段代码在后面tree控件onCheck事件中会用到。

好了,废话不多说了,开始上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$(‘#ulButtonTree‘).tree({
            url:"@Url.Action("GetButtonTree", "Res")",
            checkbox:true,
            cascadeCheck: false,
            onBeforeLoad: function (node, param) {
                var node = $(‘#ulResTree‘).tree(‘getSelected‘);
                if (node)
                    param.ResID = node.ID;
            },
            onCheck: function (node, checked) {
                var tree = $(‘#ulButtonTree‘);
                if (!eventNode) {//鼠标勾选事件初始化标致,标识鼠标勾选事件第一次遍历开始
                    eventNode = node;//将鼠标勾选时的节点保存起来,待向下 遍历时,将从此节点开始
                    treeup = true;//向上遍历标志,由鼠标勾选的节点eventNode开始向上遍历
                }
                if (treeup) {//向上遍历                  
                    var ParentNode = tree.tree("getParent", node.target);
                    if (ParentNode) {//存在上级节点
                        if (checked)//如果是选择
                            tree.tree("check", ParentNode.target);//选中上级节点。注意:如果父节点之前未选中,执行此行代码后,会再次触发onCheck事件,下面的代码暂时不会被执行;如果之前兄弟节点已被选中,那么上级节点也被选中,此行代码执行后不会触发onCheck事件,而直接执行下面的代码
                        else {//如果是取消选择
                            var isCheck = false;
                            var childNode = tree.tree("getLeafChildren", ParentNode.target);
                            for (var i = 0; i < childNode.length; i++) {//循环当前节点的父节点的所有子节点,及包含当前节点的所有兄弟节点
                                if (childNode[i].checked) {
                                    isCheck = true;//只要有兄弟节点被选中,则退出循环
                                    break;
                                }
                            }
                            if (!isCheck)//如果所有兄弟节点及当前节点都未勾选,则取消父节点的勾选
                                tree.tree("uncheck", ParentNode.target);
                        }
                    }
                    treeup = false;//向上遍历结束
                }
                //到达根部节点或向上遍历结束之后再回到原始节点开始向下遍历
                if (!treeup && eventNode) {
                    var childNode = tree.tree("getChildren", eventNode.target);//获取原始节点eventNode的所有子孙节点
                    if (checked) {//如果是选择
                        for (var i = 0; i < childNode.length; i++) {//循环所有子孙节点,全部选中
                            tree.tree("check", childNode[i].target);
                        }
                    }
                    else {//如果是取消
                        for (var i = 0; i < childNode.length; i++) {//循环所有子孙节点,全部取消勾选
                            tree.tree("uncheck", childNode[i].target);
                        }
                    }
                }
                eventNode = null;//标志本次鼠标勾选事件遍历结束
            }
        });

  好了,看看效果图吧,为了弄这个gif图片,还费了点时间,哈哈,大家有没有好的录制gif的小软件啊,推荐一下呗。

技术分享图片

以上是关于怎么让所有子节点被选中,父节点自动选中 TreeView的主要内容,如果未能解决你的问题,请参考以下文章

jstree checkbox,选择父节点时会自动选中子节点,选中全部子节点会自动选中父节点。怎么去掉此功能。

easyui Tree模拟级联勾选cascadeCheck,节点选择,父节点自动选中,节点取消,父节点自动取消选择,节点选择,所有子节点全部选择,节点取消,所有子节点全部取消勾选

Delphi TreeView 选择父节点,选择所有子节点

当我取消选中自定义树视图中的子节点复选框时,如何取消选中所有父节点

jstree中想要选中子节点,父节点就会变成选中状态,需要如何修改。

TreeView 点击触发父节点子节点的连锁反应选中与取消