delphivirtualtreeviewtvirtualstringtree

VirtualStringTree filtering done right


I'm looking for a quick way to filter nodes in a VirtualStringTree based on a filter rule, especially when the filter rule changes. There is a filter mechanism built in the VST where you can define whether the node is filtered out.

My solution right now is to determine on node initialization whether the node is filtered out. When the filter changes, I iterate through all initialized nodes and change the filter state if needed.

The problem is that the more nodes are initialized, the longer it takes to iterate through them. There are many nodes outside of the window where the filter information is not needed right now (the virtual paradigm).

The question is, is there anything like a filter invalidation system / filter events / other solutions to only touch the nodes that really needs the "filter-has-changed" information?

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;

Solution

  • There is no invalidation system that "only touches nodes that really needs the "filter-has-changed" information". In order to display correct scrollbars and the correct expandable state of all nodes, you need to review all initialized nodes if they are still to display or not. With the knowledge how your filter works, you may be able to optimize things in your for-loop and skip certain nodes. You may also consider using vst.VisibleNodes instead of InitializedNodes, but then need to also filter when a node is expanded.