WinForms中TreeView控件的扩展与使用

EXE文件方便大家测试   源码下载

TreeView控件非常的好用,在我的公文系统中,使用TreeView控件选择接收公文的人员,支持单选,可多选

现提取出来,方便大家使用

 

涉及到的知识点

1:从Xml文件中加载内容显示到TreeView控件中

复制代码
<?xml version="1.0" encoding="utf-8"?>
<根目录>
  <组 名称="校长" 用户ID="1000">
    <成员 名称="某某校长" 用户ID="9001" />
  </组>
  <组 名称="副校长" 用户ID="1000">
    <成员 名称="副校长甲" 用户ID="9002" />
    <成员 名称="副校长乙" 用户ID="9003" />
  </组>
  <组 名称="主任" 用户ID="1000">
    <成员 名称="主任甲" 用户ID="9004" />
    <成员 名称="主任乙" 用户ID="9005" />
    <成员 名称="主任丙" 用户ID="9006" />
  </组>
  <组 名称="教师" 用户ID="1000">
    <成员 名称="教师甲" 用户ID="9007" />
    <成员 名称="教师乙" 用户ID="9008" />
    <成员 名称="教师丙" 用户ID="9009" />
    <成员 名称="教师丁" 用户ID="9010" />
    <成员 名称="教师戊" 用户ID="9011" />
    <成员 名称="教师己" 用户ID="9012" />
  </组>
  <组 名称="班主任" 用户ID="1000">
    <成员 名称="教师甲" 用户ID="9007" />
    <成员 名称="教师乙" 用户ID="9008" />
  </组>
  <组 名称="学科" 用户ID="1000">
    <组 名称="语文教师" 用户ID="1000">
      <成员 名称="教师甲" 用户ID="9007" />
      <成员 名称="教师丁" 用户ID="9010" />
    </组>
    <组 名称="数学教师" 用户ID="1000">
      <成员 名称="教师丙" 用户ID="9009" />
      <成员 名称="教师己" 用户ID="9012" />
    </组>
  </组>
</根目录>
复制代码

加载Xml配置文件到TreeView中

private void LoadMixedTreeView()
        {
            mixedCheckBoxesTreeView1.Nodes.Clear();    // Clear any existing items
            mixedCheckBoxesTreeView1.BeginUpdate();    // Begin updating the treeview


            HiddenCheckBoxTreeNode rootNode = new HiddenCheckBoxTreeNode("某某单位");


            mixedCheckBoxesTreeView1.Nodes.Add(rootNode);


            HiddenCheckBoxTreeNode treenode;




            XmlNodeList baseNodeList = docXML.SelectNodes("根目录/组");   // Get all first level <folder> nodes


            foreach (XmlNode xmlnode in baseNodeList)       // loop through all base <folder> nodes 
            {
                string title = xmlnode.Attributes["名称"].Value;
                string id = xmlnode.Attributes["用户ID"].Value;


                treenode = new HiddenCheckBoxTreeNode(title);   // add it to the tree


                treenode.Name = id;


                rootNode.Nodes.Add(treenode);


                populateChildNodes(xmlnode, treenode);      // Get the children
            }


            mixedCheckBoxesTreeView1.EndUpdate();      // Stop updating the tree
            mixedCheckBoxesTreeView1.Refresh();


            this.mixedCheckBoxesTreeView1.Nodes[0].Expand();
        }


绑定xml数据到左侧单选TreeView
//level的作用主要是为了防止触发子节点的AfterCheck方法。 
        private int level = 1;
        //遍历 获取选中的节点的值
        //(二) 1、 多选树形控件 AfterCheck
        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (level == 1)
            {
                level = 2;
                //遍历选择所有相关子栏目
                TreeViewCheck.CheckControl(e);
                listBox1.Items.Clear();


                //遍历所有子栏目并添加到listBox中
                foreach (TreeNode node in treeView1.Nodes)
                {


                    SetMulTreeViewList(node);
                }
                label3.Text = "接收对象" + listBox1.Items.Count.ToString() + "人";
            }


        }
        //(二) 2、 设置多个树形控件列表
        public void SetMulTreeViewList(TreeNode nodes)
        {
            level = 1;
            //防止节点没有子节点被忽略
            if (nodes.Checked && nodes.Nodes.Count == 0)
            {


                selectUser = new SelectUser(nodes.Text, nodes.Name);
                if (!hasExist(selectUser))
                {
                    listBox1.Items.Add(selectUser);
                    listBox1.DisplayMember = "Name";
                    listBox1.ValueMember = "UserID";
                }


            }
            //有子节点
            foreach (TreeNode newNode in nodes.Nodes)
            {
                if (newNode.Nodes.Count > 0)
                {
                    SetMulTreeViewList(newNode);
                }
                //判断孩子节点
                else
                {
                    if (newNode.Checked && newNode.Nodes.Count == 0)
                    {


                        selectUser = new SelectUser(newNode.Text, newNode.Name);
                        if (!hasExist(selectUser))
                        {
                            listBox1.Items.Add(selectUser);
                            listBox1.DisplayMember = "Name";
                            listBox1.ValueMember = "UserID";
                        }


                    }


                }
            }
        }


        //(二) 3.  添加的项目是否已经存在
        private bool hasExist(SelectUser selectUser)
        {
            bool flag = false;
            foreach (SelectUser _Row in listBox1.Items)
            {
                if (_Row.Name == selectUser.Name && _Row.UserID == selectUser.UserID)
                    flag = true;
            }


            return flag;
        }


绑定Xml数据到上例中右侧多选TreeView

 

2:扩展TreeView控件,默认的TreeView 控件只能设置显示选中框,或者不显示选中框

如图:

  

如果要实现如下图的效果,就要对TreeView控件做一些扩展

扩展的方法来自国外的一个网站,感谢原作者

  using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;


namespace CnTreeView
{
    public class HiddenCheckBoxTreeNode : TreeNode
    {
        internal bool CheckboxHidden { set; get; }


        public HiddenCheckBoxTreeNode() { }
        public HiddenCheckBoxTreeNode(string text) : base(text) { }
        public HiddenCheckBoxTreeNode(string text, TreeNode[] children) : base(text, children) { }
        public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex) : base(text, imageIndex, selectedImageIndex) { }
        public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex, TreeNode[] children) : base(text, imageIndex, selectedImageIndex, children) { }
        protected HiddenCheckBoxTreeNode(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { }
    }
}


HiddenCheckBoxTreeNode
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;


namespace CnTreeView
{
    public class MixedCheckBoxesTreeView : TreeView
    {
        /// <summary>
        /// Specifies or receives attributes of a node
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct TV_ITEM
        {
            public int Mask;
            public IntPtr ItemHandle;
            public int State;
            public int StateMask;
            public IntPtr TextPtr;
            public int TextMax;
            public int Image;
            public int SelectedImage;
            public int Children;
            public IntPtr LParam;
        }


        public const int TVIF_STATE = 0x8;
        public const int TVIS_STATEIMAGEMASK = 0xF000;


        public const int TVM_SETITEMA = 0x110d;
        public const int TVM_SETITEM = 0x110d;
        public const int TVM_SETITEMW = 0x113f;


        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref TV_ITEM lParam);


        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);


            // trap TVM_SETITEM message
            if (m.Msg == TVM_SETITEM || m.Msg == TVM_SETITEMA || m.Msg == TVM_SETITEMW)
                // check if CheckBoxes are turned on
                if (CheckBoxes)
                {
                    // get information about the node
                    TV_ITEM tv_item = (TV_ITEM)m.GetLParam(typeof(TV_ITEM));
                    HideCheckBox(tv_item);
                }
        }


        protected void HideCheckBox(TV_ITEM tv_item)
        {
            if (tv_item.ItemHandle != IntPtr.Zero)
            {
                // get TreeNode-object, that corresponds to TV_ITEM-object
                TreeNode currentTN = TreeNode.FromHandle(this, tv_item.ItemHandle);


                HiddenCheckBoxTreeNode hiddenCheckBoxTreeNode = currentTN as HiddenCheckBoxTreeNode;
                // check if it's HiddenCheckBoxTreeNode and
                // if its checkbox already has been hidden
                if (hiddenCheckBoxTreeNode != null && !hiddenCheckBoxTreeNode.CheckboxHidden)
                {
                    // to evade repeat hiding, we set CheckboxHidden to  true
                    hiddenCheckBoxTreeNode.CheckboxHidden = true;


                    // specify attributes to update
                    TV_ITEM updatedTvItem = new TV_ITEM();
                    updatedTvItem.ItemHandle = tv_item.ItemHandle;
                    updatedTvItem.Mask = TVIF_STATE;
                    updatedTvItem.StateMask = TVIS_STATEIMAGEMASK;
                    updatedTvItem.State = 0;


                    // send TVM_SETITEM message
                    SendMessage(new HandleRef(this, Handle), TVM_SETITEM, 0, ref updatedTvItem);
                }
            }
        }


        protected override void OnBeforeCheck(TreeViewCancelEventArgs e)
        {
            base.OnBeforeCheck(e);


            // prevent checking/unchecking of HiddenCheckBoxTreeNode,
            // otherwise, we will have to repeat checkbox hiding
            if (e.Node is HiddenCheckBoxTreeNode)
                e.Cancel = true;
        }
    }
}


MixedCheckBoxesTreeView

其他相关类

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace CnTreeView
{
    public static class TreeViewCheck
    {
        /// <summary>
        /// 系列节点 Checked 属性控制
        /// </summary>
        /// <param name="e"></param>
        public static void CheckControl(TreeViewEventArgs e)
        {
            if (e.Action != TreeViewAction.Unknown)
            {
                if (e.Node != null)
                {
                    CheckParentNode(e.Node, e.Node.Checked);
                }
                if (e.Node.Nodes.Count > 0)
                {
                    CheckAllChildNodes(e.Node, e.Node.Checked);
                }
            }
        }
        #region 私有方法
        //改变所有子节点的状态
        private static void CheckAllChildNodes(TreeNode pn, bool IsChecked)
        {
            foreach (TreeNode tn in pn.Nodes)
            {
                tn.Checked = IsChecked;
                if (tn.Nodes.Count > 0)
                {
                    CheckAllChildNodes(tn, IsChecked);
                }
            }
        }
        //改变父节点的选中状态
        private static void CheckParentNode(TreeNode curNode, bool IsChecked)
        {
            bool bChecked = true;
            if (curNode.Parent != null)
            {
                foreach (TreeNode node in curNode.Parent.Nodes)
                {
                    if (node.Checked == false)
                    {
                        bChecked = false;
                        break;
                    }
                }
                if (bChecked)
                {
                    curNode.Parent.Checked = true;
                    CheckParentNode(curNode.Parent, true);
                }
                else
                {
                    curNode.Parent.Checked = false;
                    CheckParentNode(curNode.Parent, false);
                }
            }
        }
        #endregion
    }
}


TreeViewCheck

  SelectUser类,您可以根据使用情况进行替换

using System;
using System.Collections.Generic;
using System.Text;


namespace CnTreeView
{
    public class SelectUser
    {
        private string name;


        public string Name
        {
            get { return name; }
            set { name = value; }
        }




        private string userID;


        public string UserID
        {
            get { return userID; }
            set { userID = value; }
        }


        public SelectUser(string name, string userID)
        {
            this.name = name;
            this.userID = userID;
        }
    }
}


SelectUser
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Xml;
 
using System.IO;
using System.Threading;




namespace CnTreeView
{
    public partial class TreeViewDemo : Form
    {
        private XmlDocument docXML = new XmlDocument();


        public TreeViewDemo()
        {
            InitializeComponent();


          


            this.mixedCheckBoxesTreeView1.BeforeCheck += new System.Windows.Forms.TreeViewCancelEventHandler(this.myTreeView1_BeforeCheck);


            this.mixedCheckBoxesTreeView1.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.myTreeView1_AfterCheck);
             
            this.treeView1.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterCheck);
        }


        private SelectUser selectUser; 


        #region 树形控件  单选
        // (一)1、 单选树形控件 BeforeCheck
        private void myTreeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Action != TreeViewAction.Unknown)
            {
                TreeNode oldNode = this.mixedCheckBoxesTreeView1.Tag as TreeNode;
                if (oldNode != null && oldNode != e.Node)
                {
                    oldNode.Checked = false;
                }
                TreeNodeCollection nodes = this.mixedCheckBoxesTreeView1.Nodes;
                if (e.Node.Parent != null)
                {
                    nodes = e.Node.Parent.Nodes;
                }
                foreach (TreeNode node in nodes)
                {
                    if (node != e.Node)
                    {
                        node.Checked = false;
                    }
                }
                this.mixedCheckBoxesTreeView1.Tag = e.Node;
            }


        }
        // (一)2、 单选树形控件 AfterCheck
        //遍历 获取选中的节点的值
        private void myTreeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            foreach (TreeNode node in mixedCheckBoxesTreeView1.Nodes)
            {
                SetTreeViewList(node);
            }


            label3.Text = "接收对象" + listBox1.Items.Count.ToString() + "人";


        }
        //(一)、3  SetTreeViewList 遍历TreeView 设置ListBox中的内容
        public void SetTreeViewList(TreeNode nodes)
        {
            //防止节点没有子节点被忽略
            if (nodes.Checked && nodes.Nodes.Count == 0)
            {
                listBox1.Items.Clear();
                selectUser = new SelectUser(nodes.Text, nodes.Name);
                listBox1.Items.Add(selectUser);
                listBox1.DisplayMember = "Name";
                listBox1.ValueMember = "UserID";


            }
            //有子节点
            foreach (TreeNode newNode in nodes.Nodes)
            {
                if (newNode.Nodes.Count > 0)
                {
                    SetTreeViewList(newNode);
                }
                //判断孩子节点
                else
                {
                    if (newNode.Checked && newNode.Nodes.Count == 0)
                    {
                        listBox1.Items.Clear();
                        selectUser = new SelectUser(newNode.Text, newNode.Name);
                        listBox1.Items.Add(selectUser);
                        listBox1.DisplayMember = "Name";
                        listBox1.ValueMember = "UserID";


                    }


                }
            }
        }




        #endregion


        #region 树形控件  多选
        //level的作用主要是为了防止触发子节点的AfterCheck方法。 
        private int level = 1;
        //遍历 获取选中的节点的值
        //(二) 1、 多选树形控件 AfterCheck
        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (level == 1)
            {
                level = 2;
                //遍历选择所有相关子栏目
                TreeViewCheck.CheckControl(e);
                listBox1.Items.Clear();


                //遍历所有子栏目并添加到listBox中
                foreach (TreeNode node in treeView1.Nodes)
                {


                    SetMulTreeViewList(node);
                }
                label3.Text = "接收对象" + listBox1.Items.Count.ToString() + "人";
            }


        }
        //(二) 2、 设置多个树形控件列表
        public void SetMulTreeViewList(TreeNode nodes)
        {
            level = 1;
            //防止节点没有子节点被忽略
            if (nodes.Checked && nodes.Nodes.Count == 0)
            {


                selectUser = new SelectUser(nodes.Text, nodes.Name);
                if (!hasExist(selectUser))
                {
                    listBox1.Items.Add(selectUser);
                    listBox1.DisplayMember = "Name";
                    listBox1.ValueMember = "UserID";
                }


            }
            //有子节点
            foreach (TreeNode newNode in nodes.Nodes)
            {
                if (newNode.Nodes.Count > 0)
                {
                    SetMulTreeViewList(newNode);
                }
                //判断孩子节点
                else
                {
                    if (newNode.Checked && newNode.Nodes.Count == 0)
                    {


                        selectUser = new SelectUser(newNode.Text, newNode.Name);
                        if (!hasExist(selectUser))
                        {
                            listBox1.Items.Add(selectUser);
                            listBox1.DisplayMember = "Name";
                            listBox1.ValueMember = "UserID";
                        }


                    }


                }
            }
        }


        //(二) 3.  添加的项目是否已经存在
        private bool hasExist(SelectUser selectUser)
        {
            bool flag = false;
            foreach (SelectUser _Row in listBox1.Items)
            {
                if (_Row.Name == selectUser.Name && _Row.UserID == selectUser.UserID)
                    flag = true;
            }


            return flag;
        }
        #endregion


        #region 树形控件


        private void radioButton2_Click(object sender, EventArgs e)
        {
            mixedCheckBoxesTreeView1.Visible = false;
            treeView1.Visible = true;
            listBox1.Items.Clear();
            label3.Text = "接收对象0人";
            level = 2;
            CheckTreeview(treeView1, false);
            level = 1;
        }


        private void radioButton1_Click(object sender, EventArgs e)
        {
            mixedCheckBoxesTreeView1.Visible = true;
            treeView1.Visible = false;
            listBox1.Items.Clear();
            label3.Text = "接收对象0人";


            CheckTreeview(mixedCheckBoxesTreeView1, false);
        }


        //遍历TreeView 全部取消 或全部选中


        private void checkSubNodes(TreeNode treeNode, bool flag)
        {
            treeNode.Checked = flag;
            foreach (TreeNode tn in treeNode.Nodes)
            {
                checkSubNodes(tn, flag);
            }
        }


        private void CheckTreeview(TreeView treeView, bool flag)
        {


            TreeNodeCollection nodes = treeView.Nodes;
            foreach (TreeNode n in nodes)
            {
                checkSubNodes(n, flag);
            }
        }


        #endregion 


        #region 加载xml菜单




        private void LoadMixedTreeView()
        {
            mixedCheckBoxesTreeView1.Nodes.Clear();    // Clear any existing items
            mixedCheckBoxesTreeView1.BeginUpdate();    // Begin updating the treeview


            HiddenCheckBoxTreeNode rootNode = new HiddenCheckBoxTreeNode("某某单位");


            mixedCheckBoxesTreeView1.Nodes.Add(rootNode);


            HiddenCheckBoxTreeNode treenode;




            XmlNodeList baseNodeList = docXML.SelectNodes("根目录/组");   // Get all first level <folder> nodes


            foreach (XmlNode xmlnode in baseNodeList)       // loop through all base <folder> nodes 
            {
                string title = xmlnode.Attributes["名称"].Value;
                string id = xmlnode.Attributes["用户ID"].Value;


                treenode = new HiddenCheckBoxTreeNode(title);   // add it to the tree


                treenode.Name = id;


                rootNode.Nodes.Add(treenode);


                populateChildNodes(xmlnode, treenode);      // Get the children
            }


            mixedCheckBoxesTreeView1.EndUpdate();      // Stop updating the tree
            mixedCheckBoxesTreeView1.Refresh();


            this.mixedCheckBoxesTreeView1.Nodes[0].Expand();
        }


        private void LoadTreeView()
        {
            treeView1.Nodes.Clear();    // Clear any existing items
            treeView1.BeginUpdate();    // Begin updating the treeview


            TreeNode rootNode = new TreeNode("某某单位");




            treeView1.Nodes.Add(rootNode);


            TreeNode treenode;




            XmlNodeList baseNodeList = docXML.SelectNodes("根目录/组");   // Get all first level <folder> nodes


            foreach (XmlNode xmlnode in baseNodeList)       // loop through all base <folder> nodes 
            {
                string title = xmlnode.Attributes["名称"].Value;
                string id = xmlnode.Attributes["用户ID"].Value;


                treenode = new TreeNode(title);   // add it to the tree


                treenode.Name = id;


                rootNode.Nodes.Add(treenode);


                populateChildNodes(xmlnode, treenode);      // Get the children
            }


            treeView1.EndUpdate();      // Stop updating the tree
            treeView1.Refresh();


            this.treeView1.Nodes[0].Expand();
        }


        private void populateChildNodes(XmlNode oldXmlnode, TreeNode oldTreenode)
        {
            //TreeNode treenode = null;


            XmlNodeList childNodeList = oldXmlnode.ChildNodes;  // Get all children for the past node (parent)


            foreach (XmlNode xmlnode in childNodeList)  // loop through all children
            {
                string title = xmlnode.Attributes["名称"].Value;


                string id = xmlnode.Attributes["用户ID"].Value;


                TreeNode tnode = new TreeNode(title);
                tnode.Name = id;


                oldTreenode.Nodes.Add(tnode);






                //treenode = oldTreenode.Nodes.Add(title);   // add it to the parent node tree


                populateChildNodes(xmlnode, tnode);  // get any children for this node
            }
        }


        #endregion


        private void TreeViewDemo_Load(object sender, EventArgs e)
        {
            docXML.Load(AppDomain.CurrentDomain.BaseDirectory + "\\menu.xml");


            LoadMixedTreeView();


            LoadTreeView();
        }


    }
}


TreeViewDemo

 

 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值