前に、あなたが間違ったことをしていると言いましたが、今ならその理由がわかります。
ツリー コントロールを使用してデータを保存しています。データを表示するためのものです。唯一の仕事がデータを保存することである別のデータ構造が必要です。おそらくツリーになりますが、ツリーコントロールではありません。ノードを表示する必要がないため、処理フォームに渡すのはこのツリー データ構造です。
データを表示するには、ツリーの最初のレベルにあるノードの数を調べ、ツリー コントロールのRootNodeCountプロパティをその数に設定します。AddNewNodeコントロールはその数のノードを割り当てます — コントロールへの入力などの一括操作を呼び出さないでください。ツリーが以前に表示されていないノードを画面に表示しようとすると、OnInitNodeイベント ハンドラーが起動されます。ここでノードを初期化し、データ構造の値に関連付けます。ツリー コントロールは、どのノードが初期化されているかを示します —PVirtualNodeポインタと、その親に対してどのノードであるかを示すインデックスの両方を介して。ノードを初期化するときに、ノードに子があるかどうかをツリーに伝えます。何人かは言う必要ない子供はまだ; コントロールが知りたい場合は、別のイベントで尋ねます。
データを単なるプレゼンテーションから切り離したので、プレゼンターの存続期間がデータの存続期間と異なることを心配する必要がなくなりました。処理フォームは、ツリー ビュー コントロールが最初からデータを所有していないため、ツリー ビュー コントロールがまだ存在するかどうかに関係なくデータを処理できます。
以下も参照してください。
ノードのレベルは 1 つだけだとおっしゃいました。それで大丈夫です。レベルが 1 つしかないツリーは、より一般的にはリストとして知られています。リストを追跡するために使用できるものがいくつかあります。最も単純なのは配列です。を使用することもTList、独自のリンク リストを作成することもできます。ツリー コントロールに注目したいので、この例では配列を使用します。
各ノードのデータがレコードで表されていると仮定すると、TDataこれらの配列が得られます。
var
Data: array of TData;
配列に情報をロードしたら、ソースに関係なく、ツリー コントロールにデータを入力する準備が整います。これは 2 行のコード (コントロールが空の状態で開始した場合は 1 行) と同じくらい簡単です。
Tree.ResetNode(nil); // remove all existing nodes from tree
Tree.RootNodeCount := Length(Data); // allocate new nodes for all data
ツリーは、それらのノードのいずれかに関する詳細情報が必要であると判断すると、OnInitNodeイベントをトリガーすることから始めます。ノードのフィールドは、特定のツリー ノードに対応するレコードIndexを見つけるのに十分であるため、そのイベントに対して行う必要があることはあまりありません。TData
procedure TJeffForm.TreeInitNode(Sender: TBaseVirtualTree;
ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
Assert(Node.Index < Length(Data), 'More nodes than data elements!?');
InitialStates := []; // If the node had children, or if it should be
// initially disabled, you'd set that here.
end;
OnGetTextツリーがそれ自体をペイントする場合、イベントをトリガーして、表示されているノードごとに表示するテキストを尋ねます。ノードのIndexフィールドは、その親に対してどのアイテムであるかを示します。(リストがあるだけなので、そのインデックスはリスト内のインデックスに対応します。)
procedure TJeffForm.TreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: UnicodeString);
begin
if TextType = ttStatic then
exit;
case Column of
NoColumn,
0: CellText := Data[Node.Index].Name;
1: CellText := 'Second column';
else
Assert(False, 'Requested text for unexpected column');
end;
end;
TData上記では、 という名前の文字列フィールドがNameあり、それがメイン列に表示されるものであると想定しました。ツリーが 2 列目以降のテキストを要求すると、アサーション エラーが発生し、まだ製品をリリースする準備ができていないことが示されます。
ノード インデックスを使用して、完全に別個の配列データ構造を調べる方法に注目してください。ツリー コントロールを完全に破棄しても、データはまだ存在します。処理フォームでデータを処理する必要がある場合Dataは、ツリー コントロールではなく、配列を渡してください。