选择TreeView节点

时间:2012-12-24 14:00:39

标签: c# .net treeview parent

我有一个TreeNode,我需要允许用户只选择一个子节点作为父节点。 例如:

-Car
---Ferrari
---Lamborghini
---Porsche

-Shoes
---Nike
---Puma
---Adidas

我可以选择"法拉利"和#34; Nike",但不是" Car"中的其他孩子。或"鞋子"。我该怎么做呢? 在我这样做之后,我需要将父母和孩子的文字连成这样:汽车:法拉利 你能帮帮我吗? 问候。

2 个答案:

答案 0 :(得分:0)

如果每棵树需要一个选择,我建议使用两个TreeView。我还要问你是否需要使用TreeViews,或者两个ListBoxes或ComboBoxes是否更合适。

如果你不知道你将拥有多少'树',但你知道它们有多深,你可以使用两个或更多ListBoxes(或ListViews)来显示一个列表列表:

Categories:
   Shoes: Nike
   Cars:  Ferrari
   Fruits: Apple (selected)

Selected Category (Fruits):
   Apple (selected)
   Orange
   Pear
   Kiwi

答案 1 :(得分:0)

您可以处理BeforeCheck事件并清除兄弟姐妹复选框,例如:

private bool skipEvents = false; // this flag to avoid infinite recursion

void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
{
    // if is a root (car or shoes), or it's a recursive call, just return
    if (skipEvents || e.Node.Parent == null) 
        return;
    skipEvents = true;
    foreach (TreeNode sibling in e.Node.Parent.Nodes)
    {
        // set the other siblings to unchecked
        if (sibling != e.Node)
            sibling.Checked = false;
    }
    skipEvents = false;
}

以下是连接所选父母和孩子的示例:

public string GetSelectionString()
{
    string categorySep = Environment.NewLine;
    string parentChildSep = " : ";
    StringBuilder sb = new StringBuilder();
    foreach (TreeNode root in this.treeView1.Nodes)
    {
        foreach (TreeNode node in root.Nodes)
        {
            if (node.Checked)
            {
                if (sb.Length > 0)
                    sb.Append(categorySep);
                sb.Append(root.Text);
                sb.Append(parentChildSep);
                sb.Append(node.Text);
                break;
            }
        }
    }
    return sb.ToString();
}

例如,如果选择了法拉利和美洲豹,它会返回如下字符串:

Car : Ferrari
Shoes : Puma

根据评论编辑:

此代码执行您在评论中提出的要求(选择/取消选择父母子女):

private bool skipEvents = false; // this flag to avoid infinite recursion

void treeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e)
{
    // if it's a recursive call, just return
    if (skipEvents)
        return;

    skipEvents = true;

    // it's a root (e.g. car or shoes) 
    if (e.Node.Parent == null)
    {
        // if root node is going to be checked, just cancel the action (i.e. block parent selection)
        if (!e.Node.Checked)
        {

            e.Cancel = true;
        }
    }
    else
    {
        foreach (TreeNode sibling in e.Node.Parent.Nodes)
        {
            // set the other siblings to unchecked
            if (sibling != e.Node)
                sibling.Checked = false;
        }
    }

    skipEvents = false;
}


void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
    // if it's a recursive call, just return
    if (skipEvents)
        return;

    this.skipEvents = true;

    // it's a root (e.g. car or shoes) 
    if (e.Node.Parent == null)
    {
        // root node has been unchecked, so uncheck the children
        if (!e.Node.Checked)
        {
            foreach (TreeNode child in e.Node.Nodes)
                child.Checked = false;
        }
    }
    else
    {
        // if a child node has been checked --> check the parent
        // otherwise, uncheck the parent
        e.Node.Parent.Checked = e.Node.Checked;
    }

    this.skipEvents = false;
}

<强> N.B。
TreeView类在Vista / Windows7中出现known bug关于复选框的问题 基本上,如果您双击一个复选框,它不会发生任何事件,因此这种管理将受到损害。 要解决此问题,您可以使用this post中解释的类而不是TreeView来禁用双击。