惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
博客园 - 【当耐特】
小众软件
小众软件
A
About on SuperTechFans
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
Vercel News
Vercel News
爱范儿
爱范儿
Google DeepMind News
Google DeepMind News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threatpost
人人都是产品经理
人人都是产品经理
H
Help Net Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
B
Blog
F
Full Disclosure
P
Proofpoint News Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Threat Research - Cisco Blogs
L
LangChain Blog
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Project Zero
Project Zero
I
InfoQ
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Cloudflare Blog
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Check Point Blog
K
Kaspersky official blog
WordPress大学
WordPress大学
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Securelist
T
Tenable Blog
N
News and Events Feed by Topic
The GitHub Blog
The GitHub Blog
W
WeLiveSecurity
Stack Overflow Blog
Stack Overflow Blog
O
OpenAI News
Blog — PlanetScale
Blog — PlanetScale
量子位
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
P
Proofpoint News Feed

博客园 - jenner

js 更改 onclick 事件 - jenner js 去除字符串中重复的字符 - jenner - 博客园 js 获取选中的checkbox的行的其他值 javactript关闭窗体,刷新父窗体....... - jenner - 博客园 js实现动态级联计分,级数无限制 - jenner - 博客园 winform dgv右键选择 - jenner - 博客园 DataGrid 二维表头 DataGrid导出到Excel or word javascript 对datagrid的一些操作 - jenner - 博客园 DataView 属性操作 - jenner - 博客园 javascript 判断整数 javascript控制服务器控件-js操作CheckBoxList实现全选、反选 css控制字数(控制宽度) 网站变黑白 漂浮div窗体,带停止 111 test 使用QuickCHM软件轻松编译CHM格式的文件 遍历treeView的所有节点
TreeView第三种状态的另类实现
jenner · 2007-12-03 · via 博客园 - jenner

转自:http://blog.csdn.net/am2004/archive/2007/05/22/1621349.aspx

缘起:

最近给一个WinForm项目做权限设置,需要用到树形控件(TreeView)。设置TreeView的CheckBoxes属性为true时,树形控件的每个节点前会出现一个选择框。但选择框只有两种显示外观,即选中(框中有勾)和未选中。相信很多朋友也希望能够有第三种显示外观,当节点的子节点部分选中时使用。去网上寻求方案,多是建议自己开发继承自TreeView的自定控件,在自定控件扩展属性以实现三种状态。不讨论方案的优劣性,能否有其他的方案可以快速实现?

     思路:TreeView有ImageList和ImageIndex属性,可以用该属性为每个节点定义显示的图像。如果我们自备三种状态的显示图像,在NodeMouseClick事件中控制节点应该显示那个图像,是不是也可以呢?答案是肯定的,而且不算复杂。

要点之二:我们编程之前需要确定任意某个节点被点击时(NodeMouseClick事件)的处理规则,规则明朗后程序就基本上写出来了。

//规则1:取消选定

//规则1.1:检查是否有子节点,需清除所有子节点的选定状态;

//规则1.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

//规则2:选定

//规则2.1:检查是否有子节点,设置所有子节点为选定状态

//规则2.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

     代码参考:

//设置选定和取消选定后的显示图像

        private void ButtonsTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)

        {

            //规则1:取消选定

            //规则1.1:检查是否有子节点,需清除所有子节点的选定状态;

            //规则1.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

            //规则2:选定

            //规则2.1:检查是否有子节点,设置所有子节点为选定状态

            //规则2.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

            if (e.Node.ImageIndex == 1)

            {

                e.Node.SelectedImageIndex = 0;

                e.Node.ImageIndex = 0;

                SetNodeImg11(e.Node);

                SetNodeImg12(e.Node);

            }

            else

            {

                e.Node.SelectedImageIndex = 1;

                e.Node.ImageIndex = 1;

                SetNodeImg21(e.Node);

                SetNodeImg22(e.Node);

            }

        }

        //设置节点选定状态:规则.1:检查是否有子节点,需清除所有子节点的选定状态;

        private void SetNodeImg11(TreeNode tn)

        {

            foreach (TreeNode t in tn.Nodes)

            {

                t.SelectedImageIndex = 0;

                t.ImageIndex = 0;

                if (t.Nodes.Count != 0)

                {

                    SetNodeImg11(t);

                }

            }

        }

        //设置节点选定状态:规则.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

        private void SetNodeImg12(TreeNode tn)

        {

            if (tn.Parent == null)

                return;

            int Img0Num = 0;

            int Img1Num = 0;

            int Img2Num = 0;

            //统计兄弟节点中选中情况

            foreach (TreeNode t in tn.Parent.Nodes)

            {

                if (t.ImageIndex == 0)

                    Img0Num++;

                if (t.ImageIndex == 1)

                    Img1Num++;

                if (t.ImageIndex == 2)

                    Img2Num++;

            }

            //如果兄弟节点中选中和未选中都有

            if ((Img2Num != 0) || ((Img0Num != 0) && (Img1Num != 0)))

            {

                tn.Parent.SelectedImageIndex = 2;

                tn.Parent.ImageIndex = 2;

            }

            else

            {

                tn.Parent.StateImageIndex = 0;

                tn.Parent.ImageIndex = 0;

            }

            //递归

            SetNodeImg12(tn.Parent);

        }

        //设置节点选定状态:规则.1:检查是否有子节点,设置所有子节点为选定状态

        private void SetNodeImg21(TreeNode tn)

        {

            foreach (TreeNode t in tn.Nodes)

            {

                t.SelectedImageIndex = 1;

                t.ImageIndex = 1;

                if (t.Nodes.Count != 0)

                {

                    SetNodeImg21(t);

                }

            }

        }

        //设置节点选定状态:规则.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态

        private void SetNodeImg22(TreeNode tn)

        {

            if (tn.Parent == null)

                return;

            int Img0Num = 0;

            int Img1Num = 0;

            int Img2Num = 0;

            //统计兄弟节点中选中情况

            foreach (TreeNode t in tn.Parent.Nodes)

            {

                if (t.ImageIndex == 0)

                    Img0Num++;

                if (t.ImageIndex == 1)

                    Img1Num++;

                if (t.ImageIndex == 2)

                    Img2Num++;

           }

            //如果兄弟节点中选中和未选中都有

            if ((Img2Num != 0) || ((Img0Num != 0) && (Img1Num != 0)))

            {

                tn.Parent.SelectedImageIndex = 2;

                tn.Parent.ImageIndex = 2;

            }

            else if ((Img1Num == 0) && (Img2Num == 0))

            {

                tn.Parent.SelectedImageIndex = 0;

                tn.Parent.ImageIndex = 0;

            }

            else

            {

                tn.Parent.StateImageIndex = 1;

                tn.Parent.ImageIndex = 1;

            }

            //递归

            SetNodeImg22(tn.Parent);

        }