1

I have the below sub which checks all of a node's child nodes in a Windows form treeview when the node is checked. I get the error stated in the subject whenever I click it, but this only happens when settings the checked property. If I just run the commented out MsgBox line, it works fine with no errors.

Private Sub TreeView1_AfterCheck(ByVal sender As System.Object, ByVal e As _
    TreeViewEventArgs) Handles TreeView1.AfterCheck
    For Each s As TreeNode In TreeView1.Nodes
        If s.Checked = True Then
            For i As Integer = 0 To s.Nodes.Count - 1
                MsgBox(s.Nodes(i).Text)
                s.Nodes(i).Checked = True
            Next
        End If
    Next
End Sub

As it is a StackOverflow Exception, this seemed like the best place to ask about it!

4 Answers 4

8

What's happening is that within the AfterCheck event you're 'Checking' a tree node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which fires the AfterCheck event, in which you 'Check' a node, which causes the stack overflow.

To fix, don't set Checked in an AfterCheck event handler.

Sign up to request clarification or add additional context in comments.

3 Comments

Funny and clear illustration of the problem. Could have used some formatting though ;o)
I feel a bit silly now that I didn't realise that earlier. Very funny illustration of the problem though :)
The final advice is not wrong; a bit incomplete, yes, but not wrong. The final advice would definitely fix the issue.
6

Documentation for the TreeView.AfterCheck event says:

Setting the TreeNode.Checked property from within a BeforeCheck or AfterCheck event handler causes the event to be raised multiple times and can result in unexpected behavior. To prevent the event from being raised multiple times, add logic to your event handler that only executes your recursive code if the Action property of the TreeViewEventArgs is not set to TreeViewAction.Unknown.

The event is being raised every time you call s.Nodes(i).Checked.

1 Comment

Thanks for your answer Jim. I've used a combination of yours and Patrick McDonald's answers as my final solution. Code is in the comment of Patrick's post.
1

This line:

s.Nodes(i).Checked = True

causes the event TreeView1_AfterCheck to be triggered itself. So it's an infinite loop.

You need to rewrite the code more carefully, so that you don't re-assign Checked = True if Checked is already true, and perhaps use a private field to check to see if the current event is already running upon entry.

Comments

0

Instead of iterating through all the root nodes of the TreeView, you can simply iterate through the child nodes of the checked node that raised the event:

Private Sub TreeView1_AfterCheck(ByVal sender As System.Object, ByVal e As TreeViewEventArgs) Handles TreeView1.AfterCheck
    If e.Node.Checked Then
        For Each child As TreeNode In e.Node.Nodes
            child.Checked = True
        Next
    End If
End Sub

EDIT:

You don't need to check for e.Action here, and indeed should not, for 2 reasons:

  • As you are enumerating the children of the checked node then you will not have a problem with infinite recursion you were having in your original code.
  • If you exit when e.Action = unknown, then if you have 3 levels in your treeview, it will only select the immediate children of the node you selected, and not all descendants.

2 Comments

Thanks Patrick. Below is the code I settled on using: If e.Action <> TreeViewAction.Unknown Then For Each child As TreeNode In e.Node.Nodes child.Checked = e.Node.Checked Next End If This way it automatically works to uncheck all the child nodes as well. Now how do I close a question on this website?
Never mind, found it. Who would've though it'd be that extremely obvious big fat tick on the page! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.