0

I've a TreeNode and I need to allow user to select only one child node for parent. Example:

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

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

I can select "Ferrari" and "Nike", but not other child in "Car" or "Shoes". How can I make it?
After I do this, I need to concat text of Parent and child like this: Car: Ferrari.
Can you help me?
Regards.

digEmAll
  • 56,430
  • 9
  • 115
  • 140
user1849976
  • 53
  • 1
  • 10

2 Answers2

0

If you need one selection per tree, I would suggest using two TreeViews. I would also question whether or not you need to be using TreeViews or whether two ListBoxes or ComboBoxes might be more appropriate.

If you don't know how many 'trees' you'll have, but you do know how deep they are, you could use two or more ListBoxes (or ListViews) to display basically a list of lists:

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

Selected Category (Fruits):
   Apple (selected)
   Orange
   Pear
   Kiwi
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
  • Hi, I can have N Tree.. because I manage category, so an user can select one child for parent, but I don't know how many tree are there.. – user1849976 Dec 24 '12 at 14:18
0

You could handle the BeforeCheck event and clear the siblings checkboxes, e.g. :

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

Here's an example to concatenate the parents and childs selected:

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

for example if Ferrari and Puma are selected, it returns a string like this:

Car : Ferrari
Shoes : Puma

EDIT as per comment:

This code does what you ask in your comment (selection/deselection of parents children):

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 class has a known bug that arises in Vista/Windows7 concerning checkboxes.
Basically if you double-click a checkbox it doesn't lauch any event, so this management will be compromised. To solve this issue, you can disable double-click by using the class explained in this post instead of TreeView.

Community
  • 1
  • 1
digEmAll
  • 56,430
  • 9
  • 115
  • 140
  • Thanks a lot, this is perfect for me. Can you tell me how I can concat text of selected child and his parent? – user1849976 Dec 24 '12 at 14:23
  • I have found an error in my code, check my last edit. For your last question just a couple of minutes and I'm going to update the answer again... – digEmAll Dec 24 '12 at 14:25
  • Thanks a lot you're really nice. Can I enjoy one last question? Is possible to automatically select the parent when I select a child and de-select a child when I de-select a parent? – user1849976 Dec 24 '12 at 14:35
  • Thanks a lot, you solve all my problem. Sorry but I can't give you reputation :( – user1849976 Dec 24 '12 at 15:34
  • @user1849976: don't worry ;) – digEmAll Dec 24 '12 at 15:42