`
dcrpp
  • 浏览: 44796 次
  • 性别: 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# 实现三态树源码

    `TriStateTreeView.cs`文件是C#源代码文件,它包含了三态树控件的实现。代码中可能定义了一个名为`TriStateTreeView`的类,继承自.NET Framework的`TreeView`类。在这个类中,开发者可能实现了以下关键功能: 1. **...

    C#自定义三态树

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

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

    在这个特定的案例中,"TreeView控件实现带复选框的三态树"是一个用于VSTO任务窗格的高级功能,它允许用户以图形化的方式查看和管理数据结构,特别是当数据组织成层次结构时非常有用。本文将深入探讨如何实现这样一个...

    支持三态的树和复选框

    在这个特定的案例中,我们关注的是“支持三态的树和复选框”。这个标题暗示了一个功能强大的工具,它允许用户在Swing应用中使用具有三种状态的JTree和JCheckBox组件。 首先,让我们详细解释“三态”概念。在计算机...

    C#树型菜单控件实例

    "C#树型菜单控件实例"指的是使用C#编程实现的一种交互式UI组件,它呈现为一个多级结构,类似于文件系统的目录结构,用户可以通过展开和折叠节点来浏览和选择数据。 树型菜单控件(TreeView)是Windows Forms和WPF...

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

    `Sources`目录可能包含了项目的所有源代码文件,而`SmartSolutions.Controls.Test`可能是测试目录,包含了针对这个三状态树控件的单元测试或者示例代码。 通过这个项目,开发者不仅可以了解如何扩展.NET控件以满足...

    三状态树视图控件(CustomTreeView)

    "三状态树视图控件(CustomTreeView)"是一个这样的实例,它由C#编程语言实现,专为显示三种不同状态的树形结构数据而设计。在这个项目中,开发者扩展了标准的.NET Framework TreeView控件,增加了更多的功能和灵活...

    C#实现treeview节点三种选择状态

    通过以上步骤,我们可以在C#中实现一个具备全选、未选和半选三种状态的TreeView控件。这样的功能可以极大地提高用户在处理复杂树形结构时的交互体验,特别是在需要独立控制每个节点及其子节点选中状态的情况下。

    TreeView实现三态

    "TreeView实现三态"是指在TreeView控件中,节点不仅可以是常规的选中或未选中状态,还可以有第三种状态——部分选中(或者称为半选中)。这种三态模式在某些需求下特别有用,比如多选时允许用户选择一个组内的部分项...

    三态树视图

    "三态树视图"是一种在Windows应用程序中广泛使用的用户界面元素,特别是在C#和.NET框架下开发的WinForms应用中。它扩展了标准的树形视图控件,提供了更多的状态来表示节点的选中情况,从而为目录浏览和安装程序等...

    C#OOP内部测试机试题.doc

    《深入.NET平台和C#编程》内部测试机试题主要涵盖了三个方面的知识点,分别是:C#中的WinForms应用程序设计、面向对象编程(OOP)中的多态性和XML文件的读取与数据绑定。以下是对这些知识点的详细说明: 1. **C# ...

    用C#描述的数据结构

    C#的泛型集合和多态性支持,为实现二叉树、平衡树、图的邻接矩阵和邻接列表提供了灵活的工具。书中还探讨了.NET框架中树形控件和图算法的使用。 3. **排序与查找算法**:这部分内容涵盖了各种排序和查找算法,包括...

    C#知识类库(中文)

    9. **Lambda表达式与表达式树**:Lambda表达式简化了匿名函数的写法,而表达式树则用于表示代码本身的数据结构,常用于动态查询和元编程。 10. **.NET框架**:C#是.NET框架的一部分,理解.NET Framework的基本结构...

    C#编程语言与面向对象基础教程.rar

    此外,面向对象编程是C#的一个重要组成部分,教程将涵盖类、对象、封装、继承和多态性等核心概念。通过理解这些,你可以创建可维护、可扩展的代码结构。 在C#版本的EventBus事件总线实例源码中,你将接触到事件驱动...

Global site tag (gtag.js) - Google Analytics