1
votes

I've got two methods dealing directly with my TreeView (tvTreeview - orignal name, huh?):

private void tvTreeView_MouseClick(object sender, MouseEventargs e)
{
  selectedNode = tvtreeView.HitTest(e.Location).Node;
  /* some logic */
}

and

private void cbValue_Changed(object sender, EvenArgs e)
{
  /* some logic related to changing the value that the node refers to.
   * The nodes in the TreeView are each attached to a different bool,
   * find that bool and check the value in memory matches that of the
   * dropdown combobox */
  /* clear the tree */
  tvTreeView.BeginUpdate();
  tvTreeView.Nodes.Clear();

  //re-populate and re-draw the TreeView, then call the EndUpdate method

  tvtreeView.EndUpdate();
  tvTreeView.SelectedNode = selectedNode;
  tvTreeView.SelectedNode.Expand();
}

Basically what I'm doing is re-drawing the TreeView when the value of a dropdown combobox changes. The variable selectedNode is defined at the top of the class:

public static TreeNode selectedNode;

I'm getting a NullReferenceException thrown on tvTreeView.SelectedNode,Expand(); only when the selected node is NOT a child node (ie. when it's a parent or Root). For instance, if my TreeView looks like this:

Root <- no NullReferenceException thrown
 -Parent <- no NullReferenceException thrown
   -Child <- NullReferenceException thrown
   -Child <- NullReferenceException thrown
 -Parent <- no NullReferenceException thrown
   -Child <- NullReferenceException thrown

The NullReferenceException is thrown on any of the child nodes, but not on the Parent or Root nodes.

When I place a break point (or when the exception is thrown) Visual Studio tells me that selectedNode is not null but tvTreeView.SelectedNode is; which is weird, especially because of the line:

tvTreeView.Selectednode = selectedNode();
//tvTreeView.selectedNode is Null
//selectedNode is not null

When I re-draw the TreeView, it contains the same data (it's loaded back in from memory) as when it was first drawn and nodes are added in the same order.

Am I just approaching this in the wrong manner? Why is tvtreeView.SelectedNode only null when I select a child node and not a parent/root node?

I know that when you clear the TreeView, none of the nodes exist anymore so I'm guessing that my problem is related to that, but why is the exception only thrown when the user clicks on a child node?

1
Do you remove/readd the child items but not the parent items on repopulating the treeview? - Botz3000
@Botz3000 everything is removed/readded to the TreeView when repopulating it, right down the the root node. It's not so great for overhead, but that way I'm making sure that all the information in the TreeView is correct. - Jamie Taylor
I am sure you cannot select the node because it is not an element of the treeview anymore (new nodes were generated). No idea why it works with the parent nodes though. - Botz3000

1 Answers

2
votes

The tvTreeView.Selectednode stays null because you cleared the tree. I had a similar problem, even when i tried to select an element of the tree.

Not recommended but solves the problem - instead of clear the tree you can create a new one.

 trv = new System.Windows.Forms.TreeView();
 /*build the tree*/
 trv.SelectedNode = elementOfTheTree;

Second option is to use beforeSelect event handler and force the selection action. The selectedNode react well in those event handlers. Perhaps something like this:

bool isBeforeSelectInProgress = false;
private void beforeSelectFromTrv(object sender, TreeViewCancelEventArgs e)
{
    if (isBeforeSelectInProgress)
    {
        e.Cancel = true;
        return;
    }

    isBeforeSelectInProgress = true;

    try
    {
        //save the changes and return the node that need to be focus 
        TreeNode nodeToSelect = saveChanges((TreeNode)e.Node);
        //cancel any other selection event
        e.Cancel = true;
        nodeToSelect.EnsureVisible();
        //release the event handler
        isBeforeSelectInProgress = false;
        //and than select the node you wish will be selected
        (sender as System.Windows.Forms.TreeView).SelectedNode = toSelect;
    }
    finally
    {
        isBeforeSelectInProgress = false;
    }
}