Delphi:从虚拟字符串树中删除节点后更改焦点

标签 delphi focus virtualtreeview tvirtualstringtree

我有一个 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;

我还希望更改能够引起一些 react ,例如设置按钮的 Enabled 属性:

procedure TMyForm.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
  btn1.Enabled := Assigned(Node);
end;

但是该解决方案存在一些问题。例如,当我使用“取消”按钮关闭表单(表单使用 ShowModal 方法打开)时,节点被释放,VSTFocusChanged 被触发,后者抛出一个由于 nil 按钮而出现异常。当然,我可以检查按钮是否已分配,但是是否有更优雅的解决方案可以在删除节点后更改焦点而不会出现这种不良效果(并且没有其他不良效果)?

最佳答案

是否有一种内置方法可以始终选择节点?

是的,有。从这些事件中删除您的代码,并将 toAlwaysSelectNode 选项包含到 TreeView TreeOptions.SelectionOptions 选项集中(例如,在 IDE 中启用它)。这个选项的评论说:

If this flag is set to true, the tree view tries to always have a node selected.

这也包括节点删除。

<小时/>

如何从 VT 事件安全更新外部控件的启用状态?

您面临的问题是您从 OnFreeNode 事件手动聚焦节点,这又触发了 OnFocusChanged 事件。并且由于当控件被销毁并且该按钮之前被销毁时节点也会被释放,因此您试图访问被销毁的控件。为了避免将来出现这种情况,您可以使用 RTL actions因为即使 VT 有 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 操作。

关于Delphi:从虚拟字符串树中删除节点后更改焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44618310/

相关文章:

windows - Delphi:通过套接字发送多个字符串?

angularjs - 如何在angularjs中选择表格中的单个项目

delphi - 具有隐藏节点的 VirtualStringTree 行的颜色

delphi - 如何让Delphi从文本文件的特定行读取到特定行

delphi - delphi中的TStream警告

android - 如何防止MediaPlayer在其他应用程序中启动

delphi - 虚拟 TreeView 。如何修改子列宽度?

delphi - 如何在TVirtualStringTree的一列中显示图标或图像?

delphi - 使用 Delphi XE 将通过 WinHTTP 下载的文件保存到磁盘

焦点问题上的 jQuery CSS 不透明度