views:

356

answers:

1

What would cause a TreeView to collapse, other than a call to the .Collapse() method on a TreeNode or the .CollapseAll() method of the TreeView?

In an application that I am developing, the TreeView will simply not behave properly. The TreeView maintains only two levels. When selecting a child of a parent node, all other nodes immediately collapse. However, there are no .Collapse() or .CollapseAll() method calls in my code whatsoever!

All properties of the TreeView are left at their defaults except the .LabelEdit property, which is set to true. The TreeView has some code associated within the AfterLabelEdit event for a simple validation/MessageBox routine.

I have tried:

  • Hooking the BeforeCollapse event of the TreeView and raising the e.CancelAction flag.

  • Manually expanding all nodes within the TreeView's AfterSelect event. (This works fine as an experiment, but I do not intend to disallow node collapse
    altogether!)

At many points within the code, I am iterating through the TreeView, node by node, to check the properties. However, no additions or deletions of nodes occur. The only TreeNode properties that are modified as the user makes selections are .ImageIndex and .SelectedImageIndex.

Other than the two solutions above, I do not have any clue as to what may be causing this error. Even if no solutions can be realized, might anyone have an idea about the proper way to go about trapping the collapse? (I have tried setting a breakpoint within the BeforeCollapse event, but it not triggered unless the user explicitly collapses the node via the mouse or keyboard. )


UPDATE:

The problem is due to chaging the .SelectedImageIndex property on any TreeNode. Changing this property causes all other nodes to collapse.

I have attempted surrounding the .SelectedImageIndex property modification code with .BeginUpdate() and .EndUpdate() calls to no avail.

How can this be avoided?

+5  A: 

This is a side effect of the way native windows work in Windows. Many of the window options are specified by style flags in the CreateWindowEx() call. Basic stuff, like what the border looks like on a form. What kind of View a ListView should have. Whether a TreeView should display checkboxes.

These styles are exposed as properties on a control. But there's a problem. Changing such a property requires the window to be recreated from scratch so that new style flags can be specified in the CreateWindowEx() call. That has side effects, the window gets completely recreated so it loses all previous state.

Windows Forms does a pretty good job of making this look smooth, restoring the previous state after recreating the window. But it there are leaks here and there. And a few outright bugs. One leak in TreeView is the exact state of which nodes are collapsed and which are not. Keeping track of this is just not practical.

Diagnose this by putting the Handle property of the TreeView in a watch window. If you see it change, you've found the property. The list of style flags is available here, you can probably map their names to their corresponding property.

Perhaps it is clear that there is no great workaround for this problem, other than avoiding changing that property. Trouble like this is what begat WPF.

Hans Passant
Thanks for the comprehensive answer! I was able to pinpoint the property that was causing the tree to be recreated and avoid using it past the point of initialization. The tree no longer forgets the node states.
James