Delphi TTreeView:按索引获取根节点计数和根节点?

Delphi TTreeView:按索引获取根节点计数和根节点?,delphi,treeview,delphi-10-seattle,Delphi,Treeview,Delphi 10 Seattle,每个TTreeNode都可以使用Node.Count提供其直接子节点的数量,并且我可以使用Node[index]通过索引获得任何子节点 我一直在搜索,但似乎这对于根节点是不可能的??我真的要自己数吗?如果是的话,最优雅的方式是什么 我希望有一个隐藏的根项,它只是将所有根节点都作为子节点,如果能够将所有类型的节点都作为子节点来处理,那不是很有帮助吗?例如,对于一个为所有节点做一些事情的递归函数来说?你是对的,TTreeView应该有这个,但它没有,我看不出有什么好的理由。但是,以下是一些需要考虑的

每个
TTreeNode
都可以使用
Node.Count提供其直接子节点的数量,并且我可以使用
Node[index]
通过索引获得任何子节点

我一直在搜索,但似乎这对于根节点是不可能的??我真的要自己数吗?如果是的话,最优雅的方式是什么


我希望有一个隐藏的根项,它只是将所有根节点都作为子节点,如果能够将所有类型的节点都作为子节点来处理,那不是很有帮助吗?例如,对于一个为所有节点做一些事情的递归函数来说?

你是对的,
TTreeView
应该有这个,但它没有,我看不出有什么好的理由。但是,以下是一些需要考虑的想法:

TTreeView
中使用的数据结构不直接支持直接子节点计数或按索引访问它们,因为它是一个链表,每个节点都链接到其父节点、其下一个和上一个同级节点以及其第一个子节点

为方便起见,
TTreeNode
对象可以为您提供所需的内容,但为此,它必须在链中循环并计数

这也意味着,访问for循环中的所有子级无论如何都不是一个好主意,就像您提到的递归函数一样——它不必要地是循环中的一个循环

相反,使用
TreeView.Items.GetFirstNode
(或
MyParentNode.getFirstChild
)直接遍历该链,然后使用
Node:=Node.getNextSibling
(这对于递归函数也非常有效)

建议:查看Vcl.ComCtrls中的实现。在此基础上,您还可以调整您要求的两个最优雅的功能,以防您仍然需要它:)

只是为了证明你应该如何而不是去做;-)


TTreeView.Items呢?它通过绝对索引返回所有节点,@MartynASure,但是它的一个项不是一个具有Nil.parent的树节点吗?当然我可以从那里获得必要的信息,它只是感觉有点麻烦,与childnodes相比,@MartynAOne节点将为
IsFirstNode
返回true。在OLH中,“IsFirstNode为第一个节点返回true,没有父节点或以前的同级节点。”我会调用GetFirstNode并使用GetNextSibling进行循环。@SertacAkyuz,正确,我无意中看到了Vcl.ComCtrls,其中TTreeNode.GetItem是使用GetFirstChild和GetNextChild完成的。。。编辑。我试着问一个好问题,在写的时候,@MartynA,我继续调查,然后不想扔掉它。。。所以我把它贴了出来,已经假设我会自己写答案:)我以前做过,似乎有些人不喜欢它。我真的很想知道为什么…我对人们回答他们自己的问题一点问题都没有,事实上我希望更多的人在没有其他人给出答案的情况下这样做。在这种情况下,我只是好奇你回答问题的措辞方式,把自己称为“你”,而不仅仅是说“在进一步考虑之后,我相信下面的答案是我的问题……”。就这些。。。
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;
for I:= 0 to TreeView.GetRootCount - 1 do
  with TreeView.GetRootItem(I) do
    Memo.Lines.Add(string.Join(#9, [AbsoluteIndex, Index, Text]));