Table of Contents

Modes

TTMSFNCTreeView supports two independent data modes that determine how node content is supplied. Choose the mode that fits your data size and update frequency; both expose the same rendering and interaction features.

Mode When to use
Collection-based Default. Nodes are stored in the Nodes collection. Best for moderate data sets where node objects need to persist between interactions.
Virtual Node data is returned on demand via OnGetNumberOfNodes and OnGetNodeText events. No collection is maintained. Best for large or dynamically computed data sets (millions of nodes).

Virtual mode

The tree retrieves values by firing events. The minimum implementation is two events.

A minimum virtual-mode tree wires OnGetNumberOfNodes and OnGetNodeText against the two columns declared in FormCreate:

procedure TForm1.FormCreate(Sender: TObject);
begin
  TreeView1.BeginUpdate;
  TreeView1.ClearNodeList;
  TreeView1.ClearNodes;
  TreeView1.ClearColumns;
  TreeView1.Columns.Add.Text := 'Column 1';
  TreeView1.Columns.Add.Text := 'Column 2';
  TreeView1.EndUpdate;
end;

procedure TForm1.TreeView1GetNumberOfNodes(Sender: TObject;
  ANode: TTMSFNCTreeViewVirtualNode; var ANumberOfNodes: Integer);
begin
  if ANode.Level = -1 then
    ANumberOfNodes := 3
  else if (ANode.Level = 0) and (ANode.Index = 0) then
    ANumberOfNodes := 5;
end;

procedure TForm1.TreeView1GetNodeText(Sender: TObject;
  ANode: TTMSFNCTreeViewVirtualNode; AColumn: Integer;
  AMode: TTMSFNCTreeViewNodeTextMode; var AText: string);
begin
  if ANode.Level = 0 then
    AText := 'Node ' + IntToStr(ANode.Index) + ' for ' + TreeView1.Columns[AColumn].Text
  else
    AText := 'Child Node ' + IntToStr(ANode.Index);
end;

OnGetNumberOfNodes

This event fires once per parent level during tree construction. Use ANode.Level to identify the level:

  • Level -1 — root level (first display).
  • Level 0 and above — child level for the node at that depth.
procedure TForm1.TreeView1GetNumberOfNodes(Sender: TObject;
  ANode: TTMSFNCTreeViewVirtualNode; var ANumberOfNodes: Integer);
begin
  if ANode.Level = -1 then
    ANumberOfNodes := 3                                   // 3 root nodes
  else if (ANode.Level = 0) and (ANode.Index = 0) then
    ANumberOfNodes := 5;                                  // 5 children for first root
end;

OnGetNodeText

Returns the text for each node column:

procedure TForm1.TreeView1GetNodeText(Sender: TObject;
  ANode: TTMSFNCTreeViewVirtualNode; AColumn: Integer;
  AMode: TTMSFNCTreeViewNodeTextMode; var AText: string);
begin
  if ANode.Level = 0 then
    AText := 'Node ' + IntToStr(ANode.Index) + ' – ' + TreeView1.Columns[AColumn].Text
  else
    AText := 'Child ' + IntToStr(ANode.Index);
end;
Virtual TreeView with root and child nodes

Virtual node identity

Each virtual node carries:

Property Type Description
Index Integer Position relative to its parent
Row Integer Global row index in the tree
Level Integer Depth; -1 = root level, 0+ = child depths
Children Integer Direct child count
TotalChildren Integer Recursive child count

Virtual tree methods

All virtual-mode operations use the Virtual suffix:

// Add and expand
pn := TreeView1.AddVirtualNode;
n := TreeView1.AddVirtualNode(pn);   // add as child of pn
TreeView1.ExpandVirtualNode(pn);

// Remove
TreeView1.RemoveVirtualNode(TreeView1.FocusedVirtualNode);

// Expand/collapse all
TreeView1.ExpandAllVirtual;
TreeView1.CollapseAllVirtual;

Collection-based mode

Nodes are stored in the Nodes collection. Each TTMSFNCTreeViewNode holds text, icons, check states, and an Extended flag per column.

procedure TForm1.PopulateTree;
var
  pn, childn: TTMSFNCTreeViewNode;
  I, C: Integer;
begin
  TreeView1.BeginUpdate;
  TreeView1.ClearNodeList;
  TreeView1.ClearNodes;
  TreeView1.ClearColumns;

  TreeView1.Columns.Add.Text := 'Column 1';
  TreeView1.Columns.Add.Text := 'Column 2';

  for I := 0 to 2 do
  begin
    pn := TreeView1.AddNode;
    for C := 0 to TreeView1.Columns.Count - 1 do
      pn.Text[C] := 'Node ' + IntToStr(I) + ' for ' + TreeView1.Columns[C].Text;

    if I = 0 then
    begin
      for C := 0 to 4 do
      begin
        childn := TreeView1.AddNode(pn);
        childn.Text[0] := 'Child Node ' + IntToStr(C);
      end;
    end;
  end;

  TreeView1.EndUpdate;
end;
Collection-based TreeView

Collection node properties

Property Description
Text[AColumn] Text value for the given column
CheckTypes[AColumn] tvntCheckBox or tvntRadioButton
Checked[AColumn] Check state
Extended When True, node spans all columns
VirtualNode Reference to the underlying TTMSFNCTreeViewVirtualNode

Collection tree methods

// Add root and child nodes
pn := TreeView1.AddNode;
pn.Text[0] := 'Parent';
n := TreeView1.AddNode(pn);  // child of pn
n.Text[0] := 'Child';

// Expand and collapse
TreeView1.ExpandNode(pn);
TreeView1.ExpandAll;
TreeView1.CollapseAll;

// Remove
TreeView1.RemoveNode(TreeView1.FocusedNode);
// equivalent:
TreeView1.FocusedNode.Free;

Switching between modes

You cannot mix virtual and collection-based operations in the same tree. If you use AddVirtualNode, call RemoveVirtualNode and the other *Virtual methods throughout. The same applies for the collection API. When using collection-based nodes and responding to events, the ANode.Node property on the virtual node gives back the collection item; the reverse direction is TTMSFNCTreeViewNode.VirtualNode.

Virtual mode events for customisation beyond text:

Event When to implement
OnGetNumberOfNodes Always — defines tree structure
OnGetNodeText Always — provides display text
OnGetNodeIcon Node icons per column
OnGetNodeCheckType Per-node checkbox/radiobutton type
OnIsNodeExpanded Initial expand/collapse state
OnIsNodeEnabled Disabled nodes
OnGetNodeHeight Variable height (HeightMode = tnhmVariable)

See also

  • Nodes — fixed vs variable height, checkboxes, extended nodes
  • Interaction — editing, filtering, sorting