如何在C#中的TreeView中显示多个复选框?

我知道如何在TreeView中为每个TreeNode显示一个CheckBox。 我想在TreeView中为每个TreeNode显示3个CheckBox。 原因是我的程序中有3个图表,每个TreeNode代表不同的系列。 我想让用户可以选择在他们喜欢的任何图表上显示每个系列。

这个(或类似的东西)可能吗? 提前致谢。

您需要拥有者绘制TreeView 。 不完全是最简单的所有者绘制控件的例子,但仍然不太难。

这是一个示例屏幕截图:

在此处输入图像描述

首先,我们创建简单的TreeNode子类来保存额外的数据:

 public class TreeNode3 : TreeNode { public string Label { get; set; } public bool Check1 { get; set; } public bool Check2 { get; set; } public bool Check3 { get; set; } public new string Text { get { return Label; } set { Label = value; base.Text = ""; } } public TreeNode3() { } public TreeNode3(string text) { Label = text; } public TreeNode3(string text, bool check1, bool check2, bool check3) { Label = text; Check1 = check1; Check2 = check2; Check3 = check3; } public TreeNode3(string text, TreeNode3[] children) { Label = text; foreach (TreeNode3 node in children) this.Nodes.Add(node); } } 

请注意,我隐藏了原始文本,基本上用字符串变量Label替换它。 我避免使用Tag所以你仍然可以自己使用它。我没有实现所有构造函数。 如果您需要ImageLists ,可能需要添加ImageIndices

现在为TreeView本身:

 using System.Windows.Forms.VisualStyles; //.. public partial class UcTreeView : TreeView { [DisplayName("Checkbox Spacing"), CategoryAttribute("Appearance"), Description("Number of pixels between the checkboxes.")] public int Spacing { get; set; } [DisplayName("Text Padding"), CategoryAttribute("Appearance"), Description("Left padding of text.")] public int LeftPadding { get; set; } public UcTreeView() { InitializeComponent(); DrawMode = TreeViewDrawMode.OwnerDrawText; HideSelection = false; // I like that better CheckBoxes = false; // necessary! FullRowSelect = false; // necessary! Spacing = 4; // default checkbox spacing LeftPadding = 7; // default text padding } public TreeNode3 AddNode(string label, bool check1, bool check2, bool check3) { TreeNode3 node = new TreeNode3(label, check1, check2, check3); this.Nodes.Add(node); return node; } private Size glyph = Size.Empty; protected override void OnDrawNode(DrawTreeNodeEventArgs e) { TreeNode3 n = e.Node as TreeNode3; if (n == null) { e.DrawDefault = true; return; } CheckBoxState cbsTrue = CheckBoxState.CheckedNormal; CheckBoxState cbsFalse = CheckBoxState.UncheckedNormal; Rectangle rect = new Rectangle(e.Bounds.Location, new Size(ClientSize.Width, e.Bounds.Height)); glyph = CheckBoxRenderer.GetGlyphSize(e.Graphics, cbsTrue ); int offset = glyph.Width * 3 + Spacing * 2 + LeftPadding; if (n.IsSelected) { e.Graphics.FillRectangle(SystemBrushes.MenuHighlight ,rect); e.Graphics.DrawString(n.Label, Font, Brushes.White, e.Bounds.X + offset, e.Bounds.Y); } else { CheckBoxRenderer.DrawParentBackground(e.Graphics, e.Bounds, this); e.Graphics.DrawString(n.Label, Font, Brushes.Black, e.Bounds.X + offset, e.Bounds.Y); } CheckBoxState bs1 = n.Check1 ? cbsTrue : cbsFalse; CheckBoxState bs2 = n.Check2 ? cbsTrue : cbsFalse; CheckBoxState bs3 = n.Check3 ? cbsTrue : cbsFalse; CheckBoxRenderer.DrawCheckBox(e.Graphics, cbx(e.Bounds, 0).Location, bs1); CheckBoxRenderer.DrawCheckBox(e.Graphics, cbx(e.Bounds, 1).Location, bs2); CheckBoxRenderer.DrawCheckBox(e.Graphics, cbx(e.Bounds, 2).Location, bs3); } protected override void OnNodeMouseClick(TreeNodeMouseClickEventArgs e) { Console.WriteLine(e.Location + " bounds:" + e.Node.Bounds); TreeNode3 n = e.Node as TreeNode3; if (e == null) return; if (cbx(n.Bounds, 0).Contains(e.Location)) n.Check1 = !n.Check1; else if (cbx(n.Bounds, 1).Contains(e.Location)) n.Check2 = !n.Check2; else if (cbx(n.Bounds, 2).Contains(e.Location)) n.Check3 = !n.Check3; else { if (SelectedNode == n && Control.ModifierKeys == Keys.Control) SelectedNode = SelectedNode != null ? null : n; else SelectedNode = n; } Console.WriteLine(" " + n.Check1 + " " + n.Check2 +" " + n.Check3 ); Invalidate(); } Rectangle cbx(Rectangle bounds, int check) { return new Rectangle(bounds.Left + 2 + (glyph.Width + Spacing) * check, bounds.Y + 2, glyph.Width, glyph.Height); } } 

几点说明:

  • 该树不支持LabelEditing 。 可行,但另一种蠕虫..
  • 该树不支持FullrowSelect为真,但实际上它仍然有效..
  • 您应该能够使用ImageListStateImageList但需要在添加节点后设置索引。
  • 不要将CheckBoxes属性设置为true! 所有三个CheckBoxes都是虚拟的,您可以在将节点转换为TreeNode3作为Check1..Check3属性后访问它们!
  • 我还没有实现三态CheckBoxes。 您可以将bool更改为可为空,然后添加click和draw事件中所需的代码。
  • 我在代码中留下了一些Console.WriteLines以便更好地进行测试。

更新我添加了SpacingPadding属性以及一些构造函数。 现在,设置示例的表单代码看起来很正常:

 ucTreeView1.Nodes.Add(new TreeNode3("Bauhaus", true, true, false)); TreeNode3 aNode = ucTreeView1.AddNode("Beatles", true, true, false); ucTreeView1.Nodes.Add(new TreeNode3("Blur", true, true, false)); ucTreeView1.Nodes.Add(new TreeNode3("Byrds", true, true, false)); ucTreeView1.Nodes.Add(new TreeNode3("Bee Gees", new TreeNode3[]{ new TreeNode3("Barry", true, false, false), new TreeNode3("Robin"), new TreeNode3("Maurice")} )); TreeNode3 aNodeA = new TreeNode3("John", true, true, false); TreeNode3 aNodeB = new TreeNode3("Paul", true, true, true); TreeNode3 aNodeC = new TreeNode3("George", true, false, true); TreeNode3 aNodeD = new TreeNode3("Ringo", true, false, false); aNode.Nodes.Add(aNodeA); aNode.Nodes.Add(aNodeB); aNode.Nodes.Add(aNodeC); aNode.Nodes.Add(aNodeD); 
 I have applied treeview nodes populated with multiple childs in one of my work, hence it can give you an idea: int k=0,L=0,totalNode=0; for (int j = 0; j < ((object[])(row[0, 0])).Length; j++) { TreeNode root = new TreeNode(); // Creating new root node root.Text = ((object[])(row[0, 1]))[j].ToString()+" "; root.Tag = ((object[])(row[0, 0]))[j].ToString(); int projectID = Convert.ToInt32(root.Tag); treeView1.Nodes.Add(root); //Adding the node totalNode++; TaskDataHandler taskData = new TaskDataHandler(); object[,] arrTask = new object[1, 2]; arrTask = taskData.GetTaskData(xdoc, AppVariable.apiToken, projectID); for (int i = 0; i < ((object[])(arrTask[0, 0])).Length; i++) { totalNode++; TreeNode child = new TreeNode(); // creating child node child.Text = ((object[])(arrTask[0, 1]))[i].ToString() + " "; child.Tag = ((object[])(arrTask[0, 0]))[i].ToString(); root.Nodes.Add(child); // adding child node } } 

请点击此链接以获取从链接添加节点中的复选框的想法: https : //msdn.microsoft.com/en-us/library/system.windows.forms.treeview.checkboxes%28v=vs.140%29的.aspx