簡體   English   中英

如何在C#中的TreeView中顯示多個復選框?

[英]How to show multiple check boxes in a TreeView in C#?

我知道如何在TreeView中為每個TreeNode顯示一個CheckBox。 我想在TreeView中為每個TreeNode顯示3個復選框。 原因是程序中有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);
    }
}

請注意,我隱藏了原始Text,並基本上將其替換為字符串變量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設置為true,但是實際上它仍然有效。
  • 您應該能夠使用ImageListStateImageList但是需要在添加節點之后設置索引。
  • 不要將CheckBoxes屬性設置為true! 這三個CheckBoxes都是虛擬的,您可以在將節點強制轉換為TreeNode3Check1..Check3屬性后訪問它們!
  • 我尚未實現三態復選框。 您可以將布爾值更改為可為空,然后在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/zh-cn/library/system.windows.forms.treeview.checkboxes%28v=vs.140%29 .aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM