封装:树形节点的封装

目的:将树形节点封装成带有泛型和事件的方法,易于操作

一、封装的节点类型

带有鼠标左键单击的节点

    /// <summary> 泛型节点 </summary> 
    public class TreeNodeClick : TreeNode
    {
        public TreeNodeClick()
        {
            this.OnClickEvent = l =>
            {

                // Todo :如果当前没有注册 默认勾选子节点第一个 
                var cNode = this.FindAll<TreeNodeClick>();

                if (cNode != null && cNode.Count > 1)
                {
                    cNode[1].OnClickEvent(cNode[1]);
                }

            };
        }

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeClick> OnClickEvent;
    }

带有鼠标右键单击的节点

    /// <summary> 右键点击行为 </summary>
    public class TreeNodeRightClick : TreeNodeClick
    {
        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeRightClick> OnRightClickEvent;

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeRightClick> OnDeleteClickEvent;
    }


支持协变的节点接口(用于协变泛型查找)

    /// <summary> 支持泛型协变接口(用来筛选指定指定T类型的继承关系) </summary>
    public interface ITreeNodeInterface<out T>
    {
        /// <summary> 协变泛型值 </summary>
        T TGetParam { get; }

    }

带有泛型的左键点击节点

    /// <summary> 泛型节点 </summary>
    public class TreeNodeClick<T> : TreeNodeClick, ITreeNodeInterface<T>
    {
        /// <summary> 节点的泛型参数 </summary>
        public T Param;

        /// <summary> 协变泛型参数 </summary>
        public T TGetParam
        {
            get { return Param; }
        }
    }

带有泛型的右键点击节点

    /// <summary> 右键点击行为 </summary>
    public class TreeNodeRightClick<T> : TreeNodeRightClick, ITreeNodeInterface<T>
    {

        //  节点的泛型参数
        public T Param;

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeRightClick<T>> OnTRightClickEvent;

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeRightClick<T>> OnTDeleteClickEvent;


        public T TGetParam
        {
            get { return Param; }
        }
    }

多个泛型关联的节点

    /// <summary> 右键点击行为 </summary>
    public class TreeNodeRightClick<T, V> : TreeNodeRightClick
    {

        /// <summary> 数据 </summary>
        public T Param;

        /// <summary> 关联 </summary>
        public V Connect;


带有是否选择的节点

    /// <summary> 泛型节点 </summary>
    public class TreeNodeSingleCheck : TreeNodeClick
    {
        /// <summary> 是否被选中 </summary>
        public bool IsChoose = false;

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeSingleCheck> OnSaveEvent;

        /// <summary> 节点的行为 </summary>
        public Action<TreeNodeSingleCheck> OnChooseEvent;

    }


数值模拟定制的节点(仅供参考)

    /// <summary> 双重介质节点 </summary>
    public class TreeNodeDoubleParam<T> : TreeNodeRightClick<T>
    {
        DoubleType _doubleType;

        // HTodo  :基质节点 
        TreeNodeRightClick<GridTable> _jzTn;

        // HTodo  :裂缝节点 
        TreeNodeRightClick<GridTable> _lfTn;

        /// <summary> 根据类型加载节点 </summary>
        public void LoadDoubleNode(DoubleType doubleType)
        {
            _doubleType = doubleType;

            //  单孔
            if (doubleType == DoubleType.DKJZMX)
            {
                return;
            }

            //  双孔
            _jzTn = new TreeNodeRightClick<GridTable>();
            _jzTn.Name = "jz";
            _jzTn.Text = "裂缝";
            this.Nodes.Add(_jzTn);

            _lfTn = new TreeNodeRightClick<GridTable>();
            _lfTn.Name = "lf";
            _lfTn.Text = "基质";
            this.Nodes.Add(_lfTn);



        }

        /// <summary> 根据索引插入节点 </summary>
        public void AddDoubleNode(int totalCount, int index, TreeNodeRightClick<GridTable> tn)
        {
            //  单孔
            if (_doubleType == DoubleType.DKJZMX)
            {
                this.Nodes.Add(tn);
                return;
            }

            //  双孔 总数必须是偶数 不以双重介质为主节点
            if (totalCount % 2 == 0)
            {
                if (totalCount / 2 < index)
                {
                    tn.Text = (index - totalCount / 2).ToString();

                    _lfTn.Param = tn.Param;
                    _lfTn.Nodes.Add(tn);

                }
                else
                {
                    _jzTn.Param = tn.Param;
                    _jzTn.Nodes.Add(tn);
                }
            }
        }

    }


二、注册和触发泛型和事件节点的方法

  	this.treeView.NodeMouseClick += new TreeNodeMouseClickEventHandler(treeView_NodeMouseClick);

        /// <summary> 节点单击事件 </summary>
        void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            TreeNode pNode = e.Node;

            if (e.Button == MouseButtons.Left)
            {
                if (pNode is TreeNodeClick)
                {
                    TreeNodeClick Tex = pNode as TreeNodeClick;

                    SelectNode = Tex;

                    if (Tex.OnClickEvent != null)
                    {
                        this.HideAllWindows();

                        Tex.OnClickEvent.Invoke(Tex);
                    }

                }
            }
            if (e.Button == MouseButtons.Right)
            {
                if (pNode is TreeNodeRightClick<int>)
                {
                    TreeNodeRightClick<int> Tex = pNode as TreeNodeRightClick<int>;
                    if (Tex.OnRightClickEvent != null)
                    {
                        Tex.OnRightClickEvent.Invoke(Tex);
                    }
                }
            }


        }


三、节点的泛型查找扩展方法

    /// <summary> winform treeview的扩展方法 </summary>
    public static class TreeViewEx
    {
        /// <summary> 遍历所有节点 执行操作方法 </summary>
        public static void Foreach(this TreeView treeView, Action<TreeNode> match)
        {
            var tns = treeView.Nodes;

            foreach (TreeNode tn in tns)
            {
                tn.Foreach(match);

            }
        }

        /// <summary> 遍历所有节点 执行操作方法 </summary>
        public static void Foreach(this TreeNode treeNode, Action<TreeNode> match)
        {
            //  执行方法
            match(treeNode);

            if (treeNode.Nodes.Count > 0)
            {
                //  遍历节点
                foreach (TreeNode tn in treeNode.Nodes)
                {
                    tn.Foreach(match);
                }
            }
        }

        /// <summary> 查找所有满足条件的节点 </summary>
        public static List<T> FindAll<T>(this TreeView treeView, Predicate<TreeNode> match) where T : class
        {
            List<T> find = new List<T>();

            var tns = treeView.Nodes;

            foreach (TreeNode tn in tns)
            {
                tn.FindAll<T>(match, ref find);
            }

            return find;
        }
        /// <summary> 查找所有满足条件的节点 </summary>
        public static void FindAll<T>(this TreeNode treeNode, Predicate<TreeNode> match, ref List<T> find) where T:class
        {

            if (treeNode == null) return;
            //  执行方法
            bool isMatch = match(treeNode);

            if (isMatch && treeNode is T)
            {

                find.Add(treeNode as T);

            }
            if (treeNode.Nodes.Count > 0)
            {
                //  遍历节点
                foreach (TreeNode tn in treeNode.Nodes)
                {
                    tn.FindAll<T>(match, ref find);
                }
            }
        }

        public static List<T> FindAll<T>(this TreeView treeView) where T:class
        {
            return treeView.FindAll<T>(l => true);
        }

        public static List<T> FindAll<T>(this TreeNode treeNode) where T : class
        {
            List<T> ts = new List<T>();

            treeNode.FindAll<T>(l => true, ref ts);

            return ts;
        }

        public static List<T> FindAll<T>(this TreeNode treeNode, Predicate<TreeNode> match) where T : class
        {
            List<T> ts = new List<T>();

            treeNode.FindAll<T>(match, ref ts);

            return ts;
        }

        /// <summary> 在本节点下查找指定节点 </summary>
        public static List<T> FindChild<T>(this TreeNode treeNode, Predicate<TreeNode> match) where T : class
        {
            List<T> find = new List<T>();

            foreach (TreeNode tn in treeNode.Nodes)
            {
                //  执行方法
                bool isMatch = match(tn);

                if (isMatch && tn is T)
                {
                    find.Add(tn as T);

                }
            }

            return find;
        }

        /// <summary> 清空指定节点节点 </summary>
        public static void ClearNodes(this TreeNode treeNode, Predicate<TreeNode> match)
        {
            List<TreeNode> temp = new List<TreeNode>();

            foreach (TreeNode tn in treeNode.Nodes)
            {

                if (match(tn))
                {
                    temp.Add(tn);

                }
            }

            foreach (var v in temp)
            {
                treeNode.Nodes.Remove(v);

            }
        }

        /// <summary> 清空指定节点节点 </summary>
        public static void ClearNodes(this TreeView tree, Predicate<TreeNode> match)
        {
            List<TreeNode> temp = new List<TreeNode>();

            foreach (TreeNode tn in tree.Nodes)
            {

                if (match(tn))
                {
                    temp.Add(tn);

                }
            }

            foreach (var v in temp)
            {
                tree.Nodes.Remove(v);

            }
        }

        /// <summary> 清空除匹配以为的节点 </summary>
        public static void ClearWithOutNodes(this TreeView tree, Predicate<TreeNode> match)
        {
            List<TreeNode> temp = new List<TreeNode>();

            foreach (TreeNode tn in tree.Nodes)
            {

                if (!match(tn))
                {
                    temp.Add(tn);

                }
            }

            foreach (var v in temp)
            {
                tree.Nodes.Remove(v);

            }
        }


        /// <summary> 对当前子节点执行指定操作</summary>
        public static void ForeachChildNode(this TreeNode treeNode, Action<TreeNode> act)
        {
            List<TreeNode> temp = new List<TreeNode>();

            foreach (TreeNode tn in treeNode.Nodes)
            {
                act(tn);
            }
        }
    }

四、泛型查找应用示例:

  	    List<TreeNodeClick<PVTW>> pvtws = this.treeView.FindAll<TreeNodeClick<PVTW>>();
            foreach (TreeNodeClick<PVTW> v in pvtws)
            {
                //  将每个分区添加泡点露点类型
                _props.Add(v.Param);
            }

五、应用逆变协变查找泛型节点示例:

var items = this.treeView.FindAll<ITreeNodeInterface<TableKey>>();

说明:TableKey是很多节点类似 节点TreeNodeClick<PVTW>中PVTW的抽象类



六、应用示例:

加载树形:

        /// <summary> 刷新底层属性节点 </summary> 
        void RefreshPropertyNode()
        {
            int x = DefineModelSZConfiger.InstanceByName(this._ecl.ID).X;
            int y = DefineModelSZConfiger.InstanceByName(this._ecl.ID).Y;
            int z = DefineModelSZConfiger.InstanceByName(this._ecl.ID).Z;

            //  净毛比
            if (GeoModelDataConfiger.InstanceByName(this._ecl.ID).IsUseNTG)
            {
                    #region - 净毛比 -

                    TreeNodeDoubleParam<NTG> dataNTG = new TreeNodeDoubleParam<NTG>();
                    NTG ntg = _grid.CreateSingle<NTG>("NTG");
                    ntg.Build(z, x, y);

                    //dataNTG.LoadDoubleNode(DefineModelSZConfiger.InstanceByName(this._ecl.ID).DoubleType);

                    foreach (var t in ntg.Tables)
                    {
                        TreeNodeRightClick<GridTable> tbn = new TreeNodeRightClick<GridTable>();
                        tbn.Name = t.IndexNum.ToString();
                        tbn.Text = t.IndexNum.ToString();
                        tbn.Param = t;
                        dataNTG.AddDoubleNode(ntg.Tables.Count, t.IndexNum, tbn);
                        tbn.OnClickEvent = l =>
                        {
                            this.HideWindow(arrayGridCapsule, false);
                            this.ActiveWindow(arrayGridCapsule);
                            this.gridLineArrayGrid.BindGridTable(ntg.Tables[t.IndexNum - 1]);
                            this.gridLineArrayGrid.BindTableUnit(UnitService.InstanceByName(this._ecl.ID).RatioUnit);

                            this.gridLineArrayGrid.RefreshGridForm();
                            this.gridLineArrayGrid.RefreshData();
                        };
                    }

                    dataNTG.Name = Guid.NewGuid().ToString();
                    dataNTG.Text = "净毛比".PadRight(ProModelDataConfiger.Instance.NameLengh);
                    this.treeView.Nodes.Add(dataNTG);
                    dataNTG.Param = ntg;
                    #endregion
                }

                
                    #region - 净厚度 -

                    TreeNodeDoubleParam<DZNET> dataDZNET = new TreeNodeDoubleParam<DZNET>();
                    DZNET dznet = _grid.CreateSingle<DZNET>("DZNET");
                    dznet.Build(z, x, y);

                    dataDZNET.LoadDoubleNode(DefineModelSZConfiger.InstanceByName(this._ecl.ID).DoubleType);

                    foreach (var t in dznet.Tables)
                    {
                        TreeNodeRightClick<GridTable> tbn = new TreeNodeRightClick<GridTable>();
                        tbn.Name = t.IndexNum.ToString();
                        tbn.Text = t.IndexNum.ToString();
                        tbn.Param = t;
                        dataDZNET.AddDoubleNode(dznet.Tables.Count, t.IndexNum, tbn);
                        tbn.OnClickEvent = l =>
                        {
                            this.HideWindow(arrayGridCapsule, false);
                            this.ActiveWindow(arrayGridCapsule);
                            this.gridLineArrayGrid.BindGridTable(dznet.Tables[t.IndexNum - 1]);
                            this.gridLineArrayGrid.BindTableUnit(UnitService.InstanceByName(this._ecl.ID).RatioUnit);


                            this.gridLineArrayGrid.RefreshGridForm();
                            this.gridLineArrayGrid.RefreshData();
                        };
                    }

                    dataDZNET.Name = Guid.NewGuid().ToString();
                    dataDZNET.Text = "净厚度".PadRight(ProModelDataConfiger.Instance.NameLengh);
                    this.treeView.Nodes.Add(dataDZNET);
                    dataDZNET.Param = dznet;

                    #endregion
                }
        }

保存数据:

      #region - 保存 -
        /// <summary> 保存 </summary>
        public void Save()
        {        
            var ntg = this.treeView.FindAll<TreeNodeRightClick<NTG>>();

            if (ntg != null && ntg.Count > 0)
            {
                //  将每个分区添加泡点露点类型
                _grid.Add(ntg[0].Param);

            }


            var dznet = this.treeView.FindAll<TreeNodeRightClick<DZNET>>();

            if (dznet != null && dznet.Count > 0)
            {
                //  将每个分区添加泡点露点类型
                _grid.Add(dznet[0].Param);

            }


            var poro = this.treeView.FindAll<TreeNodeRightClick<PORO>>();

            if (poro != null && poro.Count > 0)
            {
                //  将每个分区添加泡点露点类型
                _grid.Add(poro[0].Param);

            }
        }

        #endregion


猜你喜欢

转载自blog.csdn.net/u010975589/article/details/73250576