Please take a look to bellow code:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.StdCtrls;
type
TTreeData = record
Fields: array of String;
end;
PTreeData = ^TTreeData;
const
szVirtualTree = SizeOf(TTreeData);
type
TForm2 = class(TForm)
tree: TVirtualStringTree;
Button1: TButton;
procedure treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure treeGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
var
LTreeData: PTreeData;
Node: PVirtualNode;
cols, rows, col, row: Integer;
begin
cols:= 2;
rows:= 2;
Tree.Header.Columns.Clear;
if cols > 0 then
for col := 0 to cols - 1 do
with Tree.Header.Columns.Add do
begin
Text:= 'H' + IntToStr(col);
Width:= 80;
end;
Tree.Clear;
Tree.BeginUpdate;
if (cols> 0) and (rows > 0) then
for row := 0 to rows - 1 do
begin
Node:= Tree.AddChild(nil,nil);
Tree.ValidateNode(Node,False);
LTreeData:= Tree.GetNodeData(Node);
SetLength(LTreeData^.Fields, cols);
if cols > 0 then
for col := 0 to cols - 1 do
LTreeData^.Fields[col]:= '[' + inttostr(col) + ',' + inttostr(row) + ']';
end;
Tree.EndUpdate;
end;
procedure TForm2.treeGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize:= szVirtualTree;
end;
procedure TForm2.treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
LTreeData: PTreeData;
begin
LTreeData:= Sender.GetNodeData(Node);
CellText:= LTreeData^.Fields[Column];
showmessage(CellText);
end;
end.
After the button gets pressed the messages i get are:
[0,0]
[0,0]
[0,0]
[0,0]
[1,0]
[1,0]
[1,0]
[1,0]
[0,1]
[0,1]
[0,1]
[0,1]
[1,1]
[1,1]
[1,1]
[1,1]
Basically the GetText
is triggered 4 times for each node and each column.
Why is not getting triggered only one time? Like this: [0,0] [1,0] [0,1] [1,1]
The control uses the so called virtual paradigm. The author Mike Lischke explains this like so:
As the name already indicates, this control uses a different paradigm for tree management than other controls of this kind. It does not know anything about the data it manages (except its size), not even the captions of a node. Everything is retrieved from the application via events (or descendants via overridden methods).
The control does not keep track of the node captions. Whenever it needs to know them it fires the OnGetText
method. The control does not cache, does not remember the node captions. So if multiple parts of the control code depend on the caption then the event will be called multiple times for the same node.
The behaviour that you observe is perfectly normal and entirely to be expected. The job of your OnGetText
handler is to yield the node's text. Do not worry if it is asked the same question twice. Just make sure that you give the same answer each time!