在标准TTreeView
中,以“线性”方式从上到下迭代所有节点的最佳方法是TTreeNode.GetNext()
在循环中使用该方法while
,例如:
var
Node: TTreeNode;
Node := TreeView.GetFirstNode;
while Node <> nil do
begin
//Do something with Node...
Node := Node.GetNext;
end;
在您的自定义节点列表中,您可以通过实现可与for..in
循环一起使用的 Enumerator 来实现类似的迭代,该循环在 Delphi 2007 中引入。有关更多详细信息,请参阅 Embarcadero 的文档:
声明和语句 (Delphi):使用 For 语句对容器进行迭代
例如:
type
TMyObject = class(TObject)
private
FParent: TMyObject;
FChildren: TObjectList<TMyObject>;
public
constructor Create(AParent: TMyObject);
destructor Destroy; override;
function PreviousSibling: TMyObject;
function NextSibling: TMyObject;
function FirstChild: TMyObject;
property Parent: TMyObject read FParent;
end;
function TMyObject.PreviousSibling: TMyObject;
var
Index: Integer;
begin
Result := nil;
if FParent <> nil then
begin
Index := FParent.FChildren.IndexOf(Self);
if Index > 0 then
Result := FParent.FChildren[Index-1];
end;
end;
function TMyObject.NextSibling: TMyObject;
var
Index: Integer;
begin
Result := nil;
if FParent <> nil then
begin
Index := FParent.FChildren.IndexOf(Self);
if (Index >= 0) and (Index < (FParent.FChildren.Count-1)) then
Result := FParent.FChildren[Index+1];
end;
end;
function TMyObject.FirstChild: TMyObject;
begin
if FChildren.Count > 0 then
Result := FChildren.First
else
Result := nil;
end;
type
TMyListEnumerator = class
private
FList: TMyList;
FCurrent: TMyObject;
public
constructor Create(AList : TMyList);
function MoveNext: Boolean;
property Current: TMyObject read FCurrent;
end;
TMyList = class
private
FRoot: TMyObject;
public
function GetEnumerator: TMyListEnumerator;
end;
constructor TMyListEnumerator.Create(AList: TMyList);
begin
inherited Create;
FList := AList;
FCurrent := nil;
end;
function TMyListEnumerator.MoveNext: Boolean;
var
LObject, LParent: TMyObject;
begin
if FCurrent = nil then begin
FCurrent := FList.FRoot;
end else
begin
LObject := FCurrent.FirstChild;
if LObject = nil then
LObject := FCurrent.NextSibling;
LParent := FCurrent;
while (LObject = nil) and (LParent <> nil) do
begin
LParent := LParent.Parent;
LObject := LParent.NextSibling;
end;
FCurrent := LObject;
end;
Result := FCurrent <> nil;
end;
function TMyList.GetEnumerator: TMyListEnumerator;
begin
Result := TMyListEnumerator.Create(Self);
end;
var
MyList: TMyList;
Node: TMyObject;
// populate MyList as needed...
for Node in MyList do
begin
//Do something with Node...
end;
在后台,编译器将生成类似于以下的代码:
var
MyList: TMyList;
Node: TMyObject;
Enum: TMyListEnumerator;
// populate MyList as needed...
Enum := MyList.GetEnumerator;
try
while Enum.MoveNext do
begin
Node := Enum.Current;
//Do something with Node...
end;
finally
Enum.Free;
end;
如果您使用的是 Delphi 2006 或更早版本,for..in
则不可用,因此您必须while
明确使用上述循环。