Every TTreeNode
can give me its number of direct children using Node.Count
, and I can get any child by index using Node[Index]
.
I am searching and searching but it seems this not possible for root nodes?? Do I really have to count them myself? And if yes, what's the most elegant way to do this both?
I was expecting some hidden root-root-item which just has all the root nodes as children, wouldn't that be helpful to be able to treat all sorts of nodes the same, i.e. for a recursive function doing something for all nodes?
You are right, TTreeView
should have this, but it doesn't, and I don't see a good reason. However, here are some thoughts to take into account:
The data structure used in the TTreeView
doesn't directly support counting direct children or accessing them by index, because it is a linked list where each node links to its parent, its next and previous sibling, and its first child.
For your convenience, the TTreeNode
object is able to give you what you want, but for that it has to loop through the chain and count.
That also means, accessing all children in a for-loop is anyway not a good idea, like in the recursive function you mentioned - it would unnecessarily be a loop in a loop.
Instead, directly go through the chain using TreeView.Items.GetFirstNode
(or MyParentNode.getFirstChild
) and then a while loop with Node:= Node.getNextSibling
(that also works very well for a recursive function).
Suggestion: look at the implementation in Vcl.ComCtrls. From there, you could also adapt the two most elegant functions you ask for, in case you still need it :)
type
TTreeViewClassHelper = class helper for TTreeView
function GetRootCount: Integer;
function GetRootItem(Index: Integer): TTreeNode;
end;
function TTreeViewClassHelper.GetRootCount: Integer;
var
Node: TTreeNode;
begin
Result:= 0;
Node:= Items.GetFirstNode;
while Assigned(Node) do begin
Inc(Result);
Node:= Node.getNextSibling;
end;
end;
function TTreeViewClassHelper.GetRootItem(Index: Integer): TTreeNode;
begin
Result:= Items.GetFirstNode;
while Assigned(Node) and (Index > 0) do begin
Result:= Result.getNextSibling;
Dec(Index);
end;
end;
And just to demonstrate how you should not do it ;-)
for I:= 0 to TreeView.GetRootCount - 1 do
with TreeView.GetRootItem(I) do
Memo.Lines.Add(string.Join(#9, [AbsoluteIndex, Index, Text]));