c# TreeView实现三种选中状态

c# 项目中需要实现树状选项的勾选,有全选,半勾选,不选的状态。

因原控件中只有勾选和不勾选两种状态,所以半勾选状态需要使用代码绘制和自行定义。

勾选:Node.Checked=true

不勾选: Node.Checked=false

半勾选: Node.Checked=false && Node.ToolTipText="部分勾选"

注意:半勾选状态需要重新绘制控件需要设置控件属性DrawMode为OwnerDrawText或者OwnerDrawAll

核心逻辑一:设置父亲节点的选中状态(选中一个节点时,判断兄弟节点是否全选;取消一个节点时,需要判断兄弟节点是否有选中状态和半选中状态。由此来判断父节点的选中状态)

 //取消节点选中状态之后,取消所有父节点的选中状态
        private void setParentNodeCheckedState(TreeNode currNode, bool state)
        {
            TreeNode parentNode = currNode.Parent; //获得当前节点的父节点
            parentNode.Checked = state; //设置父节点的选中状态
            if (state == false) //当状态设置为false 
            {
                int flag = 0;
                foreach (TreeNode broNode in parentNode.Nodes) //判断该父节点的子节点中,是否有半勾选状态的选项
                {
                    if (broNode.Checked||broNode.ToolTipText.Equals("部分勾选"))
                    {
                        flag = 1;
                    }
                }
                if (flag == 1) // 有设置父节点为半勾选状态
                {
                    parentNode.ToolTipText = "部分勾选";
                    parentNode.Checked = false;
                }
                else  
                {   //设置父节点状态为 未勾选
                    parentNode.ToolTipText = "";
                    parentNode.Checked = true;
                    parentNode.Checked = false;  //需要改变节点的Checked状态,才能重新绘制控件;
                }
            }
            else {   //当父节点设置为选中状态时
                int flag = 0;
                foreach (TreeNode broNode in parentNode.Nodes)//判断该父节点的子节点下是否有未选中的节点。
                {
                    if (!broNode.Checked)
                    {
                        flag = 1;
                    }
                }
                if (flag == 1)
                {
                    parentNode.ToolTipText = "部分勾选";
                    parentNode.Checked = false;
                }
                else
                {
                    parentNode.ToolTipText = "";
                    parentNode.Checked = true;
                }
            }
            if (currNode.Parent.Parent != null) //如果父节点之上还有父节点
            {  
                setParentNodeCheckedState(currNode.Parent, state); //递归调用
            }
        }

核心逻辑二:设置子节点的选中状态

 //选中节点之后,选中节点的所有子节点
        private void setChildNodeCheckedState(TreeNode currNode, bool state)
        {
            TreeNodeCollection nodes = currNode.Nodes; //获取所有子节点
            if (nodes.Count > 0) //存在子节点
                foreach (TreeNode tn in nodes) 
                {
                    tn.Checked = state;
                    tn.ToolTipText = "";
                    setChildNodeCheckedState(tn, state);//递归调用子节点的子节点
                }
        }

设置控件监听属性AfterCheck

  private void skinTreeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action == TreeViewAction.ByMouse) //鼠标点击
            {
                //textBox1.Text = e.Node.Text;
                if (e.Node.Checked) //选中
                {                    e.Node.ToolTipText = "";
                    //选中节点之后,选中节点的所有子节点
                    setChildNodeCheckedState(e.Node, true);
                    if (e.Node.Parent != null)
                    {
                        setParentNodeCheckedState(e.Node, true);
                    }
                }  
                else  //取消选中
                {
                    e.Node.ToolTipText = "";
                    //取消节点选中状态之后,取消所有子节点的选中状态
                    setChildNodeCheckedState(e.Node, false);
                    //如果节点存在父节点,取消父节点的选中状态
                    if (e.Node.Parent != null)
                    {
                        setParentNodeCheckedState(e.Node, false);
                    }
                }
            }
        }

设置重新绘制监听DrawNode,为半勾选状态绘制新图案

  private void ClassTreeList_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            if (e.Bounds.Location.X <= 0)
            {
                return;
            }
            var treeview = sender as TreeView;
            var brush = Brushes.Black; //黑色
            if (e.Node.ToolTipText.EndsWith("部分勾选")&&e.Node.Checked==false)
            {  //判断为半勾选状态
                var location = e.Node.Bounds.Location;
                location.Offset(-10, 7);
                var size = new Size(7, 7);
                e.Graphics.FillRectangle(brush, new Rectangle(location, size)); //这里绘制的是正方形
            }
            //绘制文本
            e.Graphics.DrawString(e.Node.Text, treeview.Font, brush, e.Bounds.Left, e.Bounds.Top);
        }

 

上一篇:java中异常处理机制 throw抛出自定义业务逻辑异常 throws继续抛出 catch捕获后会自动继续抛向调用方法


下一篇:bootstrap-treeview