TreeView的扩展(转载)

本文介绍了一个自定义的TreeView控件扩展,支持多种勾选模式,包括单选、多选子节点、勾选任意节点同中父节点等。通过枚举类型定义了不同的勾选模式,并提供了设置多选选项的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Windows.Forms;
using System.Collections.Generic;

namespace X.WinForms.Controls
{
    /// <summary>
    /// 标题:TreeView 的勾选模式
    /// </summary>
    public enum TreeViewCheckMode
    {
        /// <summary>
        /// 默认(保留)
        /// </summary>
        Default = -1,

        /// <summary>
        /// 无法选择
        /// </summary>
        None = 0,
        
        /// <summary>
        /// 只能选择一项。
        /// </summary>
        One = 1,

        /// <summary>
        /// 可以选择多项。
        /// </summary>
        Multi = 2,
    }

    public enum DefaultBoolean
    {
        False = 0,
        True = 1,
        Default = 2
    }

    /// <summary>
    /// 标题:多选上级节点的模式
    /// </summary>
    public enum TreeViewParentCheckMode
    {
        AnyCheck,
        AllCheckOnSameLevel
    }

    /// <summary>
    /// 多选选项
    /// </summary>
    public class TreeViewMutiCheckOptions
    {
        private DefaultBoolean fAllowCheckParent = DefaultBoolean.True;
        private TreeViewParentCheckMode fCheckParentMode = TreeViewParentCheckMode.AnyCheck;
        private DefaultBoolean fAllowCheckChild = DefaultBoolean.True;

        /// <summary>
        /// 获取或设置一个值,它表示是否选中上级节点。
        /// </summary>
        public DefaultBoolean AllowCheckParent
        {
            get { return fAllowCheckParent; }
            set { fAllowCheckParent = value; }
        }

        /// <summary>
        /// 获取或设置一个值,它表示选中上级节点的模式。
        /// </summary>
        public TreeViewParentCheckMode CheckParentMode
        {
            get { return fCheckParentMode; }
            set { fCheckParentMode = value; }
        }

        /// <summary>
        /// 获取或设置一个值,它表示是否选中子节点。
        /// </summary>
        public DefaultBoolean AllowCheckChild
        {
            get { return fAllowCheckChild; }
            set { fAllowCheckChild = value; }
        }

        public TreeViewMutiCheckOptions(DefaultBoolean fAllowCheckParent, TreeViewParentCheckMode fCheckParentMode, DefaultBoolean fAllowCheckChild)
        {
            this.fAllowCheckParent = fAllowCheckParent;
            this.fCheckParentMode = fCheckParentMode;
            this.fAllowCheckChild = fAllowCheckChild;
        }
    }

    /// <summary>
    /// 标题:TreeView 控件扩展
    /// 描述:2010-02-28 增加几种 CheckBox 的勾选模式。
    ///        1 “单选”
    ///        2 “多选子节点”
    ///        3 “勾选任意节点同中父节点”
    ///        4 “勾选同级节点中的所有节点同进返回中父节点”
    /// </summary>
    public class TreeViewEx : TreeView
    {
        protected SysAction SysAction = new SysAction();

        private TreeViewCheckMode fCheckMode;
        private TreeViewMutiCheckOptions fMutiCheckOptions;

        /// <summary>
        /// 获取或设置一个值,它表示当前 TreeView 的勾选模式。
        /// </summary>
        public virtual TreeViewCheckMode CheckMode
        {
            get { return fCheckMode; }
            set { fCheckMode = value; }
        }

       /// <summary>
       /// 获取或设置一个值,它表示多选模式下的选项。
       /// </summary>
        public TreeViewMutiCheckOptions MutiCheckOptions
        {
            get
            {
                if (this.fMutiCheckOptions == null)
                    this.fMutiCheckOptions = new TreeViewMutiCheckOptions(DefaultBoolean.True, TreeViewParentCheckMode.AnyCheck, DefaultBoolean.True);

                return this.fMutiCheckOptions;
            }
            set { fMutiCheckOptions = value; }
        }

        /// <summary>
        /// 获取 TreeView 所有节点
        /// </summary>
        public List<TreeNode> AllNodes
        {
            get
            {
                List<TreeNode> array = new List<TreeNode>();

                foreach (TreeNode node in this.Nodes)
                {
                    array.Add(node);
                    GetAllNodes(array, node);
                }

                return array;
            }
        }

        private void GetAllNodes(List<TreeNode> array, TreeNode parentNode)
        {
            foreach (TreeNode node in parentNode.Nodes)
            {
                array.Add(node);
                GetAllNodes(array, node);
            }
        }

        protected override void OnBeforeCheck(TreeViewCancelEventArgs e)
        {
            if (!this.SysAction.Running)
            {
                if (this.CheckMode == TreeViewCheckMode.None)
                {
                    e.Cancel = true;
                }
                else if (this.CheckMode == TreeViewCheckMode.Multi)
                {
                    if (this.MutiCheckOptions.AllowCheckParent == DefaultBoolean.True)
                    {
                        if (this.MutiCheckOptions.CheckParentMode == TreeViewParentCheckMode.AnyCheck)
                        {
                            // 如果子节点有选中项,则不能取消选择。
                            bool hasCheckOne = false;

                            foreach (TreeNode node in e.Node.Nodes)
                            {
                                if (node.Checked)
                                {
                                    hasCheckOne = true;
                                    break;
                                }
                            }

                            if (hasCheckOne)
                            {
                                e.Cancel = true;
                            }
                        }
                    }
                }
            }

            base.OnBeforeCheck(e);
        }

        protected override void OnAfterCheck(TreeViewEventArgs e)
        {
            if (this.CheckMode == TreeViewCheckMode.One)
            {
                this.CheckAllNode(new List<TreeNode>(new TreeNode[] { e.Node }), false);
            }
            else if (this.CheckMode == TreeViewCheckMode.Multi)
            {
                if (this.MutiCheckOptions.AllowCheckChild == DefaultBoolean.True)
                {
                    this.CheckAllNode(e.Node, new List<TreeNode>(new TreeNode[] { e.Node }), e.Node.Checked);
                }

                if (this.MutiCheckOptions.AllowCheckParent == DefaultBoolean.True)
                {
                    if (!this.SysAction.Running)
                    {
                        DefaultBoolean allowCheckChild = this.MutiCheckOptions.AllowCheckChild;

                        try
                        {
                            this.MutiCheckOptions.AllowCheckChild = DefaultBoolean.False;
                            this.CheckParent(e.Node, this.MutiCheckOptions.CheckParentMode);
                        }
                        finally
                        {
                            this.MutiCheckOptions.AllowCheckChild = allowCheckChild;
                        }
                    }
                }
            }

            base.OnAfterCheck(e);
        }

        public virtual void CheckAllNode(bool checkedValue)
        {
            this.CheckAllNode(null, checkedValue);
        }

        public virtual void CheckAllNode(List<TreeNode> excludeNodes, bool checkedValue)
        {
            this.CheckAllNode(null, excludeNodes, checkedValue);
        }

        /// <summary>
        /// 设置某个节点及它的所有子节点的选中状态,当 parentNode 为 Null 时表示根节点。
        /// </summary>
        /// <param name="parentNode">需要设置的节点</param>
        /// <param name="excludeNodes">排除不处理的节点</param>
        /// <param name="checkedValue">选中状态</param>
        public virtual void CheckAllNode(TreeNode parentNode, List<TreeNode> excludeNodes, bool checkedValue)
        {
            if (parentNode != null && parentNode.Checked != checkedValue)
            {
                if (excludeNodes != null && !excludeNodes.Contains(parentNode))
                    this.TrySafeSetCheckValue(parentNode, checkedValue);
            }

            TreeNodeCollection nodes = (parentNode == null)
                ? this.Nodes 
                : parentNode.Nodes;

            foreach (TreeNode node in nodes)
                this.CheckAllNode(node, excludeNodes, checkedValue);
        }

        public void CheckParent(TreeNode checkedNode, TreeViewParentCheckMode mode)
        {
            TreeNode parentNode = checkedNode.Parent;

            if (parentNode == null)
                return;

            if (mode == TreeViewParentCheckMode.AnyCheck)
            {
                bool checkedValue = false;
                // 若同一级都没有选择,同时取消父节点的选择。
                foreach (TreeNode node in parentNode.Nodes)
                {
                    if (node.Checked)
                    {
                        checkedValue = true;
                        break;
                    }
                }

                this.TrySafeSetCheckValue(parentNode, checkedValue);
                this.CheckParent(parentNode, mode);
                
            }
            else if (mode == TreeViewParentCheckMode.AllCheckOnSameLevel)
            {
                bool checkedValue = true;

                foreach (TreeNode node in parentNode.Nodes)
                {
                    if (!node.Checked)
                    {
                        checkedValue = false;
                        break;
                    }
                }

                this.TrySafeSetCheckValue(parentNode, checkedValue);
                this.CheckParent(parentNode, mode);
            }
        }

        public void TrySafeSetCheckValue(TreeNode node, bool checkedValue)
        {
            if (node == null) return;

            try
            {
                this.SysAction.Begin();
                if (node.Checked != checkedValue)
                    node.Checked = checkedValue;
            }
            finally
            {
                this.SysAction.End();
            }
        }
    }

    public class SysAction
    {
        private bool fRunning = false;

        public bool Running
        {
            get { return fRunning; }
        }

        public void Begin()
        {
            this.fRunning = true;
        }

        public void End()
        {
            this.fRunning = false;
        }
    }
}

使用:

this.treeView1.CheckMode = X.WinForms.Controls.TreeViewCheckMode.Multi;
            this.treeView1.MutiCheckOptions.AllowCheckParent = DefaultBoolean.True;
            this.treeView1.MutiCheckOptions.AllowCheckChild = DefaultBoolean.True;
            this.treeView1.MutiCheckOptions.CheckParentMode = TreeViewParentCheckMode.AllCheckOnSameLevel;

转自:https://social.msdn.microsoft.com/Forums/zh-CN/d0d60151-f433-4ba2-abe5-e4524885208f/treeview?forum=visualcshartzhchs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值