I have a subclass of System.Windows.Forms.TreeView
that's manually "bound" to a set of hierarchical data. I want the user to be able to edit the labels of the tree, and have the changes reflected back to the data. So I set LabelEdit
to true and overrode OnAfterLabelEdit
to the tune of:
protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e)
{
base.OnAfterLabelEdit(e);
TreeNode node = e.Node;
if (PassesSomeValidation(e.Label))
{
MyDataNode dataNode = node.Tag as MyDataNode;
dataNode.SomeBoundValue = e.Label;
int oldIndex = node.Index;
int newIndex = RepositionChangedDataNode(dataNode);
TreeNode parent = node.Parent;
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
}
else
{
e.CancelEdit = true;
}
}
RepositionChangedDataNode()
re-sorts the data and returns the index into which the change node moved after sorting. I was hoping I could simply move the edited node to reflect this move.
The problem is that this causes the node to stay in edit mode! I've tried calling EndEdit()
, cloning the node before inserting it, setting LabelEdit
to false and back to true, wrapping the change in BeginUpdate()
/EndUpdate()
, and various combinations of these ideas, but none of them have any effect.
The culprit seems to be the insertion. Even if I attempt to insert a totally new node, it will go into edit mode immediately.
So, is there any way to make TreeView
not behave this way? And if not, is there a good workaround?
Some ideas I've considered:
- Set a custom TreeViewNodeSorter. Would prefer not to have to sort my data twice, though.
- Set a flag and delay the remove-insert step until some point after AfterLabelEdit. It works to do it during WndProc, but this feels like a big kludge that is likely to fail somehow.
Use
BeginInvoke()
to push the remove-insert step back onto the message queue like so:BeginInvoke(new MethodInvoker(delegate( { parent.Nodes.RemoveAt(oldIndex); parent.Nodes.Insert(newIndex, node); }));
This works and seems cleaner to me than #2, but I know this is probably not how
BeginInvoke()
was intended to be used, and that it may have repercussions that my very limited knowledge of the message pump cannot predict.