【问题标题】:Select TreeView Node选择树视图节点
【发布时间】:2013-05-28 16:45:47
【问题描述】:

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

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

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

我可以选择“Ferrari”和“Nike”,但不能选择“Car”或“Shoes”中的其他孩子。我怎样才能做到?
完成此操作后,我需要像这样连接父母和孩子的文本:汽车:法拉利。
你能帮帮我吗?
问候。

【问题讨论】:

  • 你的意思是现在不能选择“汽车”和“鞋子”?
  • 赢取表格。我的意思是我只能选择 ONE CAR 和 ONE SHOES。

标签: c# .net treeview parent


【解决方案1】:

您可以处理 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();
}

例如,如果选择了 Ferrari 和 Puma,则返回如下字符串:

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;
}

注意
TreeView 类有一个 known bug 出现在 Vista/Windows7 中与复选框有关。
基本上,如果您双击一个复选框,它不会启动任何事件,因此这种管理将受到影响。 要解决此问题,您可以使用this post 中解释的类而不是TreeView 来禁用双击。

【讨论】:

  • 非常感谢,这对我来说是完美的。你能告诉我如何连接选定孩子和他父母的文本吗?
  • 我在我的代码中发现了一个错误,请检查我上次的编辑。对于您的最后一个问题,只需几分钟,我将再次更新答案...
  • 非常感谢你真的很好。我可以享受最后一个问题吗?是否可以在我选择子项时自动选择父项,在我取消选择父项时自动取消选择子项?
  • 非常感谢,您解决了我所有的问题。对不起,我不能给你声誉:(
  • @user1849976:别担心;)
【解决方案2】:

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

如果您不知道您将拥有多少“树”,但您知道它们有多深,您可以使用两个或多个 ListBox(或 ListView)来显示一个列表列表:

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

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

【讨论】:

  • 嗨,我可以拥有N棵树..因为我管理类别,所以用户可以选择一个孩子作为父母,但我不知道有多少棵树..
猜你喜欢
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
相关资源
最近更新 更多