views:

116

answers:

3

I have a TreeView with check boxes, and when a user checks a child node, I want to go up the tree and check each parent. However, for some reason my application blows up whenever I touch the parent node. For the nodes in my tree, I've extended TreeNode to create my own objects with some data that I need to store in them, but I still reference them as TreeNodes when checking/unchecking. My code looks like this:

//checkBox checked event handler
    if (node.Parent != null)
    {
        checkAllParents(node.Parent);
    }
//

private void checkAllParents(TreeNode node)
{
    node.Checked = true;
    if (node.Parent != null)
    {
       checkAllParents(node.Parent);
    }
}
A: 

It must be a infinite recursion that is blowing the stack (a stack overflow no less). node.Parent must never be evaluating to null. It won't be caught in a try catch because your code isn't throwing an exception, you are just causing a stack overflow and it is the .net frameworkthat throw the exception. You will also be triggering the recursion multiple times, every time you set node.Checked = true; you will fire of the event handler again but you also call check all parents again, i would remove the recursive call to check all parents and just set the node to checked, the event handler will do the recursion for you.

Ben Robinson
I took out the recursion and just had it do the first Parent node and it still crashes.
alexD
Step through it with a debugger, how many times is it called? does it crash on the first call? What is the stack trace?
Ben Robinson
A: 

If you really have a circular reference then you would get a stack overflow, which cannot be caught. Try to modify your code to get rid of the recursion:

// checkBox checked event handler
checkAllParents(node);

private void checkAllParents(TreeNode node)
{
  var parent = node.Parent;
  while (parent != null) {
  {
    parent.Checked = true;
    parent = parent.Parent;
  }
}

If app enters an infinite loop then you do have a circular reference. You could further modify the code to catch circular references:

private void checkAllParents(TreeNode node)
{
  var parent = node.Parent;
  var visitedNodes = new List<TreeNode>();
  while (parent != null)
  {
    if (visitedNodes.Contains(parent))
      throw new InvalidOperationException("Circular reference!");
    visitedNodes.Add(parent);
    parent.Checked = true;
    parent = parent.Parent;
  }
}

Of course this is not the right place to handle circular references. But if it helps..

Patko
+1  A: 

Ok, figured it out. It wasn't a circular reference but it was most certainly circular in nature. This was a big dumb mistake on my part..in the event handler I was using recursion to check DOWN the tree as well...I implemented this a while ago and didn't really think about it, so when I added another piece of recursion to check up the tree I ended up with an infinite loop between the recursion function and the event handler (which was getting called every time the recursive function checked one of the nodes..the After_checked event). Bah.

alexD
So you took your stack overflow to StackOverflow?
Michael Todd
Naturally=)Oh and my fix was to remove the event handler when I entered the handler function, perform the recursion, then add the event handler back at the end of the handler function. Works perfect now.
alexD
@alexD: +1 for posting your answer. I suggest you click the checkbox to accept it as the answer.
John Saunders