`
dcrpp
  • 浏览: 44474 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

C#三态树控件

    博客分类:
  • C#
阅读更多

参考了网上的一些例子,修改了一下。可以实现全选,全部去选,反选等功能。效果如附件图。

 

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace WindowsApplication1.DCR.View
{
	public partial class TriStateTreeView : TreeView
	{
		private const int STATE_UNCHECKED = 0; //unchecked state
		private const int STATE_CHECKED = 1; //checked state
		private const int STATE_MIXED = 2; //mixed state (indeterminate)

		//create a new ThreeStateTreeView
		public TriStateTreeView(): base()
		{
			
		}

		public void UpdateView()
		{
			this.SetNodesState(this.Nodes);
		}

		public void SelectAll()
		{
			this.SetNodesState(this.Nodes,STATE_CHECKED);
		}

		public void UnselectAll()
		{
			this.SetNodesState(this.Nodes,STATE_UNCHECKED);
		}

		public void AntiSelect()
		{
			this.SetNodesToAntiState(this.Nodes);
		}

		//returns a value indicating if all children are checked
		public static bool IsAllChildrenChecked(TreeNode parent)
		{
			return IsAllChildrenSame(parent, STATE_CHECKED);
		}

		//returns a value indicating if all children are unchecked
		public static bool IsAllChildrenUnchecked(TreeNode parent)
		{
			return IsAllChildrenSame(parent, STATE_UNCHECKED);
		}

		//initialize all nodes state image
		private void SetNodesState(TreeNodeCollection nodes,int state)
		{
			foreach (TreeNode node in nodes)
			{
				node.StateImageIndex = state;
				if (state == STATE_CHECKED)
				{
					node.Checked = true;
				}
				else 
				{
					node.Checked = false;    
				}

				if (node.Nodes.Count != 0)
				{
					SetNodesState(node.Nodes, state);
				}
			}
		}

		private void SetNodesState(TreeNodeCollection nodes) {
			foreach (TreeNode node in nodes)
			{
				if (node.Checked)
				{
					node.StateImageIndex = STATE_CHECKED;
				}
				else 
				{
					node.StateImageIndex = STATE_UNCHECKED;
				}
				UpdateParent(node);

				if (node.Nodes.Count != 0)
				{
					SetNodesState(node.Nodes);
				}
			}
		}

		private void SetNodesToAntiState(TreeNodeCollection nodes) 
		{
			foreach (TreeNode node in nodes)
			{
				if (node.Checked)
				{
					node.StateImageIndex = STATE_UNCHECKED;
					node.Checked = false;
				}
				else
				{
					node.StateImageIndex = STATE_CHECKED;
					node.Checked = true;
				}
				UpdateParent(node);

				if (node.Nodes.Count != 0)
				{
					SetNodesToAntiState(node.Nodes);
				}
			}
		}        

		//update children state image with the parent value
		private void UpdateChildren(TreeNode parent)
		{
			int state = parent.StateImageIndex;
			foreach (TreeNode node in parent.Nodes)
			{
				node.StateImageIndex = state;
				if (node.Nodes.Count != 0)
				{
					UpdateChildren(node);
				}
			}
		}

		//update parent state image base on the children state
		private void UpdateParent(TreeNode child)
		{
			TreeNode parent = child.Parent;
			if (parent == null)
			{
				return;
			}

			if (child.StateImageIndex == STATE_MIXED)
			{
				parent.StateImageIndex = STATE_MIXED;
			}
			else if (IsAllChildrenChecked(parent))
			{
				parent.StateImageIndex = STATE_CHECKED;
			}
			else if (IsAllChildrenUnchecked(parent))
			{
				parent.StateImageIndex = STATE_UNCHECKED;
			}
			else
			{
				parent.StateImageIndex = STATE_MIXED;
			}
			UpdateParent(parent);
		}        

		//returns a value indicating if all children are in the same state
		private static bool IsAllChildrenSame(TreeNode parent, int state)
		{
			foreach (TreeNode node in parent.Nodes)
			{
				if (node.StateImageIndex != state)
				{
					return false;
				}
				if (node.Nodes.Count != 0 && !IsAllChildrenSame(node, state))
				{
					return false;
				}
			}
			return true;
		}

		//build the checked, unchecked and indeterminate images
		private static Image GetStateImage(CheckBoxState state, Size imageSize)
		{
			Bitmap bmp = new Bitmap(16, 16);
			using (Graphics g = Graphics.FromImage(bmp))
			{
				Point pt = new Point((16 - imageSize.Width) / 2, (16 - imageSize.Height) / 2);
				CheckBoxRenderer.DrawCheckBox(g, pt, state);
			}
			return bmp;
		}


		protected override void OnHandleCreated(EventArgs e)
		{
			base.OnHandleCreated(e);
			this.StateImageList = new ImageList();            
			using (Graphics g = base.CreateGraphics())
			{
				Size glyphSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal);
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.UncheckedNormal, glyphSize));
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.CheckedNormal, glyphSize));
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.MixedNormal, glyphSize));
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.UncheckedDisabled, glyphSize));
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.CheckedDisabled, glyphSize));
				this.StateImageList.Images.Add(GetStateImage(CheckBoxState.MixedDisabled, glyphSize));
			}
		}

		//check if user click on the state image
		protected override void OnMouseClick(MouseEventArgs e)
		{
			base.OnMouseClick(e);
			if (e.Button == MouseButtons.Left)
			{
				TreeViewHitTestInfo info = base.HitTest(e.Location);
				if (info.Node != null && info.Location == TreeViewHitTestLocations.StateImage)
				{
					TreeNode node = info.Node;
					switch (node.StateImageIndex)
					{
						case STATE_UNCHECKED:
						case STATE_MIXED:
							node.StateImageIndex = STATE_CHECKED;
							break;
						case STATE_CHECKED:
							node.StateImageIndex = STATE_UNCHECKED;
							break;
					}
					UpdateChildren(node);
					UpdateParent(node);
				}
			}
		}

		//check if user press the space key
		protected override void OnKeyDown(KeyEventArgs e)
		{
			base.OnKeyDown(e);
			if (e.KeyCode == Keys.Space)
			{
				if (base.SelectedNode != null)
				{
					TreeNode node = base.SelectedNode;
					switch (node.StateImageIndex)
					{
						case STATE_UNCHECKED:
						case STATE_MIXED:
							node.StateImageIndex = STATE_CHECKED;
							break;
						case STATE_CHECKED:
							node.StateImageIndex = STATE_UNCHECKED;
							break;
					}
					UpdateChildren(node);
					UpdateParent(node);
				}
			}
		}

		//swap between enabled and disabled images
		protected override void OnEnabledChanged(EventArgs e)
		{
			base.OnEnabledChanged(e);

			for (int i = 0; i < 3; i++)
			{
				Image img = this.StateImageList.Images[0];
				this.StateImageList.Images.RemoveAt(0);
				this.StateImageList.Images.Add(img);
			}
		}
	}
}

 

namespace WindowsApplication1.DCR.View
{
	partial class TriStateTreeView
	{
		/// <summary>
		/// 必需的设计器变量。
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary> 
		/// 清理所有正在使用的资源。
		/// </summary>
		/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region 组件设计器生成的代码

		/// <summary>
		/// 设计器支持所需的方法 - 不要
		/// 使用代码编辑器修改此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}

		#endregion
	}
}
 

 

示例代码:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            TreeNode root = new TreeNode("所有院系");
            triStateTreeView.Nodes.Add(root);

            TreeNode xi1 = new TreeNode("中文系");
            root.Nodes.Add(xi1);
            TreeNode xi2 = new TreeNode("数学系");
            root.Nodes.Add(xi2);
            TreeNode xi3 = new TreeNode("物理系");
            root.Nodes.Add(xi3);

            TreeNode ban1 = new TreeNode("中文一班");
            xi1.Nodes.Add(ban1);
            TreeNode ban2 = new TreeNode("中文二班");
            xi1.Nodes.Add(ban2);
            TreeNode ban3 = new TreeNode("中文三班");
            xi1.Nodes.Add(ban3);
            ban3.Checked = true;

            triStateTreeView.UpdateView();
        }

        private void buttonSelectAll_Click(object sender, EventArgs e)
        {
            this.triStateTreeView.SelectAll();
        }

        private void buttonUnSelectAll_Click(object sender, EventArgs e)
        {
            this.triStateTreeView.UnselectAll();
        }

        private void buttonAntiSelect_Click(object sender, EventArgs e)
        {
            this.triStateTreeView.AntiSelect();
        }
    }
}
 

 

 

  • 大小: 15.9 KB
分享到:
评论
3 楼 逸尘23 2013-09-16  
能不能给一些详尽的说明呢,也在codeproject看到过一些关于三态的文章,但是更想自己试试,你基本是贴出的代码,可以读得懂,但是对于初学者来说还是需要更详细的说明。谢谢你的分享!
2 楼 wangcaiwq 2013-04-07  
非常感谢,太好用了。
1 楼 meabox 2011-08-24  
不错,挺好用!谢谢分享!

相关推荐

    c# 三态treeview控件 v1.1

    2、纯粹的三态树结构,未添加父子节点联动等效果,给控件使用者更多的自由 3、增加三态的树节点类型,直接把状态保存在树节点中,而不是勉强地在treeview控件里面打补丁,使用更流畅 4、应用csc3.5的技术,直接扩展...

    C#三态和只读性扩展树控件

    1:三态树:实现树控件的三态方式实现。 2:只读树:实现select和checkbox控制,同时解决树控件只读时滚动条无法使用的缺陷。 3:只核选一个节点:只可CheckBox一个节点,其它自动却除,从而实现唯一性Check。

    c# 三态treeview控件

    2、纯粹的三态树结构,未添加父子节点联动等效果,给控件使用者更多的自由 3、增加三态的树节点类型,直接把状态保存在树节点中,而不是勉强地在treeview控件里面打补丁,使用更流畅 4、应用csc3.5的技术,直接扩展...

    C#自定义三态树

    三态树:实现树控件的三态方式实现。只读树:实现select和heckbox控制,同时解决树控件只读时滚动条无法使用的缺陷。 只核选一个节点:只可CheckBox一个节点,其它自动却除,从而实现唯一性Check。

    C# 实现三态树源码

    此控件的的功能如下: 用三种不同的图片来表示子级全选,部分选择,还是本身选,

    TreeView控件实现带复选框的三态树.zip

    C# Excel开发 VSTO任务窗格TreeView控件实现带复选框的三态树设计。能够指示状态树的各种情况。全选、半选、未选。可以很方便的看到树内部的选择情况

    三状态树(Treeview)控件源代码

    C# 程序实现一个能够表示节点三种状态的树状控件,它继承与TreeView,它的三种状态为选中、非选中、部分节点选中.

    ASTreeView 1.4.0

    一个强大的树控件,支持拖拽,右键菜单修改删除,支持ajax载入节点,支持图标,支持三态checkbox. 在线演示:http://www.astreeview.com

    ASTreeView 1.0

    一个强大的树控件,支持拖拽,右键菜单修改删除,支持ajax载入节点,支持图标,支持三态checkbox.

Global site tag (gtag.js) - Google Analytics