我有一个System.Windows.Forms.TreeView
的子类,它被手动“绑定”到一组分层数据。我希望用户能够编辑树的标签,并将更改反映回数据。因此,我将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()
重新排序数据并返回更改节点在排序后移动到的索引。我希望我可以简单地移动已编辑的节点以反映此移动。
问题是这导致节点保持编辑模式!我尝试调用EndEdit()
,在插入节点之前克隆节点,将LabelEdit
设置为false并返回true,将更改包含在BeginUpdate()
/ EndUpdate()
中,以及各种组合这些想法,但没有一个有任何影响。
罪魁祸首似乎是插入。即使我尝试插入一个完全 new 节点,它也会立即进入编辑模式。
那么,有没有办法让TreeView
不这样做?如果没有,是否有一个好的解决方法?
我考虑过的一些想法:
使用BeginInvoke()
将删除插入步骤推回到消息队列中,如下所示:
BeginInvoke(new MethodInvoker(delegate(
{
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
}));
这对我来说比#2更有效,但我知道这可能不是BeginInvoke()
的意图,并且可能会对我对消息泵的知识非常有限无法预测产生影响
答案 0 :(得分:3)
如果您将LabelEdit
的{{1}}设置为TreeView
,则新添加的节点将不会处于编辑模式。
您只需处理用户想要编辑标签的情况:为false
的{{1}}事件创建处理程序,您可以按位置获取单击的节点。将MouseClick
设为TreeView
并致电LabelEdit
。在true
事件的处理程序结束时(以及在适当的时间点调用BeginEdit()
后),再次将AfterLabelEdit
设置为EndEdit(...)
。
这对我有用,而使用BeginInvoke的解决方案只改变了最后一个节点处于编辑模式。
答案 1 :(得分:1)
尝试创建一个全局变量,让我们说:
private bool _allowEdit;
将其初始化为true
,
OnAfterLabelEdit
方法中的在更改后将其设置为false
:
... int oldIndex = node.Index;
int newIndex = RepositionChangedDataNode(dataNode);
TreeNode parent = node.Parent;
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
**_allowEdit = false;**
}
else ...
然后像这样捕获OnBeforeLabelEdit
事件:
protected override void OnBeforeLabelEdit(NodeLabelEditEventArgs e)
{
base.OnBeforeLabelEdit(e);
e.CancelEdit = !_allowEdit;
_allowEdit = true;
}
我注意到在'AfterLabelEdit'被触发后,'BeforeLabelEdit'被重新启动。这就是为什么你必须在那里停止它。
答案 2 :(得分:0)
如果您正在使用数据绑定,那么更新数据源(SomeBoundValue)是否应该触发刷新节点?也许您可以强制货币经理重新填充树视图....如果您担心性能,您可以使用一种排序算法,该算法适用于几乎已经排序的数据(例如,NOT quicksort - merge或heapsort come记住)
或者你可以完全省去数据绑定并手动处理重新定位,因为你已经在RepositionChangedDataNode()的一半......
答案 3 :(得分:0)
您可以尝试在添加新节点之前解开OnEdit处理程序并在之后重新挂钩。我以前见过这种行为,这就是我处理它的方式。