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
0and 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 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 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.
Related events
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) |
Related API
TTMSFNCTreeViewTTMSFNCTreeViewData—TTMSFNCTreeViewNode,TTMSFNCTreeViewVirtualNode
See also
- Nodes — fixed vs variable height, checkboxes, extended nodes
- Interaction — editing, filtering, sorting