我有一个 System.Windows.Forms.TreeView
的子类,它手动“绑定(bind)”到一组分层数据。我希望用户能够编辑树的标签,并将更改反射(reflect)回数据。所以我将 LabelEdit
设置为 true 并将 OnAfterLabelEdit
设置为:
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()
重新排序数据并返回排序后更改节点移动到的索引。我希望我可以简单地移动编辑的节点来反射(reflect)这一移动。
问题是这会导致节点停留在编辑模式!我试过调用 EndEdit()
,在插入之前克隆节点,将 LabelEdit
设置为 false 并返回 true,将更改包装在 BeginUpdate()
/EndUpdate()
,以及这些想法的各种组合,但它们都没有任何效果。
罪魁祸首似乎是插入。即使我尝试插入一个全新的新节点,它也会立即进入编辑模式。
那么,有什么方法可以让 TreeView
不这样吗?如果没有,是否有好的解决方法?
我考虑过的一些想法:
- 设置自定义 TreeViewNodeSorter。不过,我宁愿不必对我的数据进行两次排序。
- 设置一个标志并将删除-插入步骤延迟到 AfterLabelEdit 之后的某个时间点。它可以在 WndProc 期间执行此操作,但这感觉像是一个大杂烩,很可能会以某种方式失败。
使用
BeginInvoke()
将删除-插入步骤推回消息队列,如下所示:BeginInvoke(new MethodInvoker(delegate( { parent.Nodes.RemoveAt(oldIndex); parent.Nodes.Insert(newIndex, node); }));
这对我来说比 #2 更有效,但我知道这可能不是
BeginInvoke()
的预期用途,而且它可能会产生影响,我对它的了解非常有限消息泵无法预测。
最佳答案
如果将 TreeView
的 LabelEdit
设置为 false
,新添加的节点将不会处于编辑模式。
您只需处理用户想要编辑标签的情况:为 TreeView
的 MouseClick
事件创建一个处理程序,您可以在其中获取被点击的节点按位置。将 LabelEdit
设置为 true
并调用 BeginEdit()
。在 AfterLabelEdit
事件的处理程序结束时(以及在适当的位置调用 EndEdit(...)
之后),将 LabelEdit
设置为再次为 false
。
这对我有用,而使用 BeginInvoke 的解决方案最后只更改了哪个节点处于编辑模式。
关于c# - 我可以在 AfterLabelEdit 期间将节点插入到 TreeView 中而不开始编辑它们吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/668078/