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);
        }

原文地址:https://www.cnblogs.com/yhood/p/11532787.html

时间: 2024-08-19 00:00:53

c# TreeView实现三种选中状态的相关文章

实现CheckBox的三种选中状态(全选、半选、不选)在GridView中模拟树形的功能

度娘了很多帖子,只说三种状态要用图片替换来做,但没找到有用的例子,被逼自己写了一个 三方控件肯定是很多的,如jstree,可以直接用 由于公司的UDS限制,不能上传图片,只能文字说明了. 就是要在gridview中实现如下效果:一级.二级因为三级没有全部选中而显示半选状态 ?一级    ?二级       三级1        三级2 js↓ $(function(){ BindCheckNode(); $("span[name^='lblCheck']").click(checkBo

进程三种基本状态

进程的三种基本状态: (1)       就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态.一个系统会将多个处于就绪状态的进程排成一个就绪队列. (2)       执行状态:进程已获CPU,正在执行.单处理机系统中,处于执行状态的进程只一个:多处理机系统中,有多个处于执行状态的进程. (3)       阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻.(这种状态又称等待状态或封锁状态) 通常导致进程阻塞的典型事件有:请求I/

持久化类的三种实例状态

一个持久化类的实例可能处于三种不同状态中的某一种.这三种状态的定义则与所谓的持久化上下文(persistence context)有关.hibernate的session对象就是这个所谓的持久化上下文. 瞬态:该实例从未与任何持久化上下文关联过.它没有持久化标识(相当于主键值). 持久化:实例目前与某个持久化上下文有关联.它拥有持久化标识(相当于主键值),并且可能在数据库中有一个对应的行.对于某一个特定的持久化上下文,hiberanate保证持久化标识与java标识(其值代表对象在内存中的位置)

hibernate的三种对象状态

1  上一个 project 2 三种状态的区分关键在于 a)有没有ID b)ID在数据库中有没有 c)在内存中有没有(session缓存) 3 三种状态: a)transient:内存中一个对象,没ID,缓存中也没有 b)persistent:内存中有,缓存中有,数据库有(ID) c)detached:内存有,缓存没有,数据库有,ID 4 对这三种状态需要关注的问题是在该状态下如果进行数据库的操作会发生什么结果,比 如改变属性的值会不会发出update语句?

模拟操作系统中进程的三种基础状态与内存的分配和回收(最佳适配算法)

利用键盘模拟进程的三种操作状态,并且使用C++中的list模板模拟内存的分配和回收. 能够模拟进程的创建与撤销过程 l可对进程的状态进行全面的控制 按先进先出方式管理就绪和阻塞队列,能够按队列形式输出进程状 用PCB代表进程,用全局变量表示进程的个数. 1 #include <iostream> 2 #include <list> 3 #include <numeric> 4 #include <algorithm> 5 #include<stdlib

Git中三种文件状态及其转换

Git作为一种版本控制解决方案,由于其具有的分布式特性,正被越来越多的用户熟知,一些有名的开源项目,如:Linux kernel,CakePHP,Ruby on Rails等,都在使用Git进行版本管理. 在Git中,文件状态是一个非常重要的概念,不同的状态对应不同的操作.因此,要想熟练掌握Git的用法,需要了解Git的几种文件状态. 为了说明的方便,现在初始化一个项目,也就是将项目所在目录纳入Git的管理之下.假设项目目录为hello_world,初始化之后,在目录下新建README.txt文

Linux中atime、mtime、ctime三种时间状态

atime:access time 最近一次访问时间 mtime:modify time 最近一次修改时间(指的是修改文件内容,数据内容) ctime:change time 最近一次属性改变时间,inode节点信息被修改时间(大小.属组.属主.权限) touch.chmod.chown都会改变该值 1.当mtime改变时,ctime必须改变,因为文件大小等属性改变 2.mtime改变时,atime不一定改变. #echo "this is a test" >> /etc/

Git中三种文件状态及其转换和git适用命令

原文地址:https://www.cnblogs.com/hnhycnlc888/p/11456738.html

01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态

以下属于不明来源资料: 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根据对象和当前会话的关联状态,我们可以把对象分为三种: 瞬时对象:对象刚刚建立.该对象在数据库中没有记录,也不在ISession缓存中.如果该对象是自动生成主键,则该对象的对象标识符为空. 持久化对象:对象已经通过NHibernate进行了持久化,数据库中已经存在对应的记录.如果该对象是自动生成主键,