TreeView第三种状态的另类实现

 
TreeView 第三种状态的另类实现
 
     缘起: 最近给一个WinForm项目做权限设置,需要用到树形控件(TreeView)。设置TreeView的CheckBoxes属性为true时,树形控件的每个节点前会出现一个选择框。但选择框只有两种显示外观,即选中(框中有勾)和未选中。相信很多朋友也希望能够有第三种显示外观,当节点的子节点部分选中时使用。去网上寻求方案,多是建议自己开发继承自TreeView的自定控件,在自定控件扩展属性以实现三种状态。不讨论方案的优劣性,能否有其他的方案可以快速实现?
     思路: TreeView 有ImageList和ImageIndex属性,可以用该属性为每个节点定义显示的图像。如果我们自备三种状态的显示图像,在NodeMouseClick事件中控制节点应该显示那个图像,是不是也可以呢?答案是肯定的,而且不算复杂。
     要点之一: 需设置TreeView的CheckBoxes属性为false,准备三个图片(图片地址:http://album.pixplayer.com/208003_242/),我们用ImageIndex等于0、1、2分别代表该节点未选中、选中、子节点部分选中三种状态,不再考虑使用节点的Checked属性。最终效果图片(图片地址:http://album.pixplayer.com/208003_242/
要点之二: 我们编程之前需要确定任意某个节点被点击时(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);
        }
 
 
 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值