码迷,mamicode.com
首页 > Windows程序 > 详细

WinForms中TreeView控件的扩展与使用

时间:2015-03-01 23:47:34      阅读:357      评论:0      收藏:0      [点我收藏+]

标签:

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

 

WinForms中TreeView控件的扩展与使用

标签:

原文地址:http://www.cnblogs.com/networkcomms/p/4307733.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!