正确完成 VirtualStringTree 过滤

VirtualStringTree filtering done right

我正在寻找一种快速方法来根据过滤规则过滤 VirtualStringTree 中的节点,尤其是当过滤规则发生变化时. VST内置了过滤机制,可以定义节点是否被过滤掉。

我现在的解决方案是在节点初始化时判断节点是否被过滤掉。当过滤器发生变化时,我会遍历所有已初始化的节点并根据需要更改过滤器状态。

问题是初始化的节点越多,遍历它们的时间就越长。在 window 之外有许多节点 现在 (虚拟范例)不需要过滤器信息。

问题是,是否有类似过滤器失效系统/过滤器事件/其他解决方案来只接触真正需要"filter-has-changed"信息的节点?

procedure TfrmMain.vstInitNode(Sender: TBaseVirtualTree; ParentNode, 
          Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  Data: PMyDataType;
begin
  Data  := Sender.GetNodeData(Node);
  Data^ := GetData(Node.Index);

  if IsNodeFiltered(Data^) then Include(InitialStates, ivsFiltered);
end;

procedure TfrmMain.OnFilterRuleChanged();
var
  Node: PVirtualNode;
  Data: PMyDataType;
begin
  vst.BeginUpdate;
  try
    for Node in vst.InitializedNodes do
    begin
      Data := vst.GetNodeData(Node);
      vst.IsFiltered[Node] := IsNodeFiltered(Data^);
    end;
  finally
    vst.EndUpdate;
  end;
end;

没有"only touches nodes that really needs the "filter-has-changed“信息”的失效系统。为了显示正确的滚动条和所有节点的正确可展开状态,您需要检查所有已初始化的节点是否仍要显示。了解过滤器的工作原理后,您可以优化 for 循环中的内容并跳过某些节点。您也可以考虑使用 vst.VisibleNodes 而不是 InitializedNodes,但是当节点展开时还需要进行过滤。