tags:

views:

484

answers:

2

I've added checkboxes to my treeview, and am using the AfterSelect event (also tried AfterChecked).

My tree view is like this

1 State
1.1 City1
1.2 City2
1.3 City3
2 State
2.1 City1
2.2 City2
2.3 City3

etc.

I'm trying to run an event, so when a checkbox is clicked, the tag is added to an array ready for processing later. I also need to use it so if a state is clicked, it selects all the cities under that leaf.

treeSections.AfterSelect += node_AfterCheck;

private void node_AfterCheck(object sender, TreeViewEventArgs e)
{
    MessageBox.Show("testing");
}

The above code works on the treeview if it has no heirarchy. But don't work on the treeview with the states and cities unless the text/label for each leaf is double clicked.

Any ideas?

+1  A: 

I suggest using the combination of TreeView.NodeMouseClick and TreeView.KeyUp events... the click event will provide you the clicked node via event args and with the keyup you can use the currently selected node. Follow the example below...

//This is basic - you may need to modify logically to fit your needs
void ManageTreeChecked(TreeNode node)
{
   foreach(TreeNode n in node.Nodes)
   {
      n.Checked = node.Checked;
   }
}

private void convTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
   ManageTreeChecked(e.Node);
}
private void convTreeView_KeyUp(object sender, KeyEventArgs e)
{
   if (e.KeyCode == Keys.Space)
   {
      ManageTreeChecked(convTreeView.SelectedNode);
   }
}

Using the node given each event you can now cycle through the Nodes collection on that node and modify it to be checked/unchecked given the status of the checked status of the node you acted upon.

You can even get fancy enough to uncheck a parent node when all child nodes are unchecked. If you desire a 3-state treenode (All Checked, Some Checked and None Checked) then you have to create it or find one that has been created.

Enjoy, best of luck.

Jamie Altizer
A: 

Some code for you to consider :

Not considered here :

  1. what to about which node is selected when checking, when a child node selection forces a parent node to be selected (because all other child nodes are selected).

  2. could be other cases related to selection not considered here.

Assumptions :

  1. you are in a TreeView with a single-node selection mode

  2. only two levels of depth, as in OP's sample ("heavy duty" recursion not required)

  3. everything done with the mouse only : extra actions like keyboard keypress not required.

  4. if all child nodes are checked, parent node is auto-checked

  5. unchecking any child node will uncheck a checked parent node

  6. checking or unchecking the parent node will set all child nodes to the same check-state

...

    // the current Node in AfterSelect
    private TreeNode currentNode;

    // flag to prevent recursion
    private bool dontRecurse;

    // boolean used in testing if all child nodes are checked
    private bool isChecked;

    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        // prevent recursion here
        if (dontRecurse) return;

        // set the currentNode
        currentNode = e.Node;

        // for debugging
        //Console.WriteLine("after check node = " + currentNode.Text);

        // select or unselect the current node depending on checkstate
        if (currentNode.Checked)
        {
            treeView1.SelectedNode = currentNode;
        }
        else
        {
            treeView1.SelectedNode = null;
        }

        if(currentNode.Nodes.Count > 0)
        {
            // node with children : make the child nodes
            // checked state match the parents
            foreach (TreeNode theNode in currentNode.Nodes)
            {
                theNode.Checked = currentNode.Checked;
            }
        }
        else
        {
            // assume a child node is selected here
            // i.e., we assume no root level nodes without children

            if (!currentNode.Checked)
            {
                // the child node is unchecked : uncheck the parent node
                dontRecurse = true;

                    currentNode.Parent.Checked = false;

                dontRecurse = false;
            }
            else
            {
                // the child node is checked : check the parent node 
                // if all other siblings are checked
                // check the parent node
                dontRecurse = true;

                    isChecked = true;

                    foreach(TreeNode theNode in currentNode.Parent.Nodes)
                    {
                       if(theNode != currentNode)
                       {
                           if (!theNode.Checked) isChecked = false;
                       }
                    }

                    if (isChecked) currentNode.Parent.Checked = true;

                dontRecurse = false;
            }

        }
    }
BillW