Delphi:从虚拟字符串树中删除节点后更改焦点
我有一个TVirtualStringTree
类型的组件(我们称它为VST
)。 它具有列表形式的节点,即所有节点都处于同一级别。 我想在删除节点(使用DeleteNode
方法)并使用OnFreeNode
事件后更改焦点:
procedure TMyForm.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
NewFocus: PVirtualNode;
begin
NewFocus := VST.GetNext(Node);
if not Assigned(newFocus) then
NewFocus := VST.GetPrevious(Node);
if Assigned(NewFocus) then
begin
VST.FocusedNode := NewFocus;
VST.Selected[NewFocus] := True
end;
end;
我还希望更改引起一些反应,例如设置按钮的Enabled
属性:
procedure TMyForm.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
btn1.Enabled := Assigned(Node);
end;
但是解决方案存在一些问题。 例如,当使用“取消”按钮关闭窗体(表单使用ShowModal
方法打开)时,节点将被释放, VSTFocusChanged
被触发,并且由于nil按钮后者会引发异常。 当然,我可以检查按钮是否已分配,但是在删除没有这种不良效果(并且没有其他不良效果)的情况下更改焦点后,是否有更好的解决方案?
是否有内置的方法来始终选择一个节点?
就在这里。 从这些事件中删除你的代码,包括toAlwaysSelectNode选项树视图TreeOptions.SelectionOptions选项集(例如启用它的IDE)。 这个选项的评论说:
如果此标志设置为true,则树视图会尝试始终选择一个节点。
这也包括节点删除。
如何从VT事件安全地更新外部控制的启用状态?
您遇到的问题是,您正在从OnFreeNode事件手动关注节点,从而触发OnFocusChanged事件。 而且,由于节点在控制被销毁并且该按钮之前被销毁时也被释放,所以您试图访问被销毁的控件。 为避免将来出现这种情况,您可以使用RTL操作,因为即使具有csDestroying状态信号(包括像OnStructureChange这样的事件 ),并且操作是一种安全的解决方法,VT也会触发很多事件。
像这样的东西应该安全工作(我不是行动OnUpdate事件的粉丝):
procedure TMyForm.VSTStructureChange(Sender: TBaseVirtualTree; Node: PVirtualNode;
Reason: TChangeReason);
begin
{ ActionDeleteNode is assigned to the button's Action property; SelectedCount
is a bit paranoic here because if you use the toAlwaysSelectNode option, at
least one node should be always selected, so RootNodeCount > 0 could do the
same here }
ActionDeleteNode.Enabled := Sender.SelectedCount > 0;
end;
没有RTL操作,您可以安全地更新该按钮状态,例如在执行操作之后,例如在删除节点之后:
VST.DeleteNode(VST.FocusedNode);
ButtonDeleteNode.Enabled := VST.SelectedCount > 0;
但有了这个,你可能会失去同步并编写更多的代码。 因此使用RTL操作是我喜欢的。
链接地址: http://www.djcxy.com/p/39835.html上一篇: Delphi: Changing focus after deleting a node from a virtual string tree