ノート
長い投稿で申し訳ありませんが、必要なときにギャップを埋めるのではなく、できるだけ多くの情報を掲載するのが最善だと思います.
これにも Delphi のタグを付けており、Delphi XE を所有し、現在も使用していますが、現在は Lazarus をプライマリ IDE として使用しています。新しい Delphi バージョンを購入する余裕がなく、Lazarus がより安定していることは理にかなっています。 Lazarus に切り替えます。
この質問については、プロジェクト ソースの zip 添付ファイルを含めましたが、Lazarus で書かれていますが、私が持っている質問に本当に役立つので、最初の段落にコメントがあります。
概要
質問に、TLists としていくつかのクラスを所有するオブジェクトがあります。
このデータを Treeview で表しますが、実行時に動的に作成されるため、ツリーに存在するレベルとノードの数を知る方法はありません。私が設定した 1 つの制限は、トップ レベル ノードが固定されることです。つまり、それらを削除したり、名前を変更したりすることはできません。これらは、私が RootGroups と呼ぶものです。
ツリービューにはアイテムとグループが取り込まれ、ツリービューに追加されたすべてのノードには、各アイテムを正しく識別するためにデータに割り当てられた独自のオブジェクトがあります。先に進む前に、より良いアイデアを提供するために、スクリーンショットの例を示します。
ご覧のとおり、一番上にObject1RootとObject2Rootの 2 つのノードがあります。右側のボタンに気付いた場合、グループとアイテムをツリービューに追加できますが、ツリービューのその部分に属していない場合は無効になります。たとえば、 Object1Root の下に Object2Group または Object2Item を追加することはできません。
基本的に、ツリービュー内のすべてのものには、オブジェクトへの独自のポインターがあります。ベースオブジェクトから派生している各オブジェクト。このベース オブジェクトには、次のように、ツリー ビュー内で見つかった位置を格納するためのプロパティがあります。
type
TBaseObject = class
private
FName: string;
FGroup: string;
FNodeLevel: Integer;
FNodeIndex: Integer;
public
constructor Create(AName: string);
destructor Destroy; override;
published
property Name: string read FName write FName;
property Group: string read FGroup write FGroup;
property NodeLevel: Integer read FNodeLevel write FNodeLevel;
property NodeIndex: Integer read FNodeIndex write FNodeIndex;
end;
次に、次のように、ベース オブジェクトから他のクラスを派生させることができます。
type
TObject1RootGroup = class(TBaseObject)
public
constructor Create(AName: string);
destructor Destroy; override;
procedure ToSave(const XMLDoc: IXMLDocument; var Root, Node: IXMLNode);
end;
TObject1Group = class(TBaseObject)
public
constructor Create(AName: string);
destructor Destroy; override;
procedure ToSave(const XMLDoc: IXMLDocument; var Root, Node: IXMLNode);
end;
TObject1Item = class(TBaseObject)
private
FSomeVal1: string;
FSomeVal2: string;
public
constructor Create(AName: string);
destructor Destroy; override;
procedure ToSave(const XMLDoc: IXMLDocument; var Root, Node: IXMLNode);
published
property SomeVal1: string read FSomeVal1 write FSomeVal1;
property SomeVal2: string read FSomeVal2 write FSomeVal2;
end;
これらすべてのクラスを保持するメイン オブジェクトは次のようになります。
type
TMyObject = class(TObject)
private
FName: string;
FObject1Groups: TList;
FObject1Items: TList;
FObject2Groups: TList;
FObject2Items: TList;
protected
procedure FreeObjects;
public
constructor Create(AName: string);
destructor Destroy; override;
procedure Save(FileName: string);
function Load(Filename: string): Boolean;
published
property Name: string read FName write FName;
property Object1Groups: TList read FObject1Groups;
property Object1Items: TList read FObject1Items;
property Object2Groups: TList read FObject2Groups;
property Object2Items: TList read FObject2Items;
end;
メイン オブジェクトを XMLに保存するときは、最初に TreeView 全体を反復処理してから、各オブジェクトに Parent、Level、Index などのノード データを割り当てます。最初の画像に基づく出力 XML ファイルは次のようになります。
注: オブジェクトに何も書き込んでいないので、SomeVal の部分は重要ではありません。
本当に私がすべきことは、ツリービューが表現されているのと同じように XML に保存することです。私はまだ XML に慣れてきているので、XML にはあまり詳しくありませんが、出力は次のようになるはずです: (メモ帳で記述)
<XML Name="test.xml">
<Counts Object1Groups="3" Object1Items="5" Object2Groups="2" Object2Items="1" />
<TObject1RootGroup Name="Object1Root" Group="" NodeLevel="0" NodeIndex="0"
<TObject1Item Name="Item1" Group="Object1Root" NodeLevel="1" NodeIndex="0" SomeVal1="" SomeVal2="" />
<TObject1Item Name="Item2" Group="Object1Root" NodeLevel="1" NodeIndex="1" SomeVal1="" SomeVal2="" />
<TObject1Group Name="Group1" Group="Object1Root" NodeLevel="1" NodeIndex="2" />
<TObject1Item Name="Item3" Group="Object1Root" NodeLevel="1" NodeIndex="3" SomeVal1="" SomeVal2="" />
<TObject1Group Name="Group2" Group="Object1Root" NodeLevel="1" NodeIndex="4" />
<TObject1Item Name="Item1" Group="Group2" NodeLevel="2" NodeIndex="0" SomeVal1="" SomeVal2="" />
<TObject1Group Name="Group1" Group="Group2" NodeLevel="2" NodeIndex="1" />
<TObject1Item Name="Item1" Group="Group1" NodeLevel="3" NodeIndex="0" SomeVal1="" SomeVal2="" />
<TObject2RootGroup Name="Object2Root" Group="" NodeLevel="0" NodeIndex="1"
<TObject2Group Name="Group1" Group="Object2Root" NodeLevel="1" NodeIndex="0" />
<TObject2Group Name="Group2" Group="Object2Root" NodeLevel="1" NodeIndex="1" />
<TObject2Item Name="Item1" Group="Group2" NodeLevel="2" NodeIndex="0" SomeVal1="" SomeVal2="" />
</XML>
その後、XML から TreeView を読み込むことができました。問題は、私が現在のように XML を保存する方法しか本当に知らないことです。ある種の再帰などが必要であることを知っており、これは私が苦労する場所であり、特に XML ファイルからツリーを再構築することです。
付属品
実際のプロジェクト コードを読みやすく理解しやすい例に分解するのに数時間かかりました。これは Lazarus で記述され、OmniXML ライブラリを使用しています。プロジェクト ファイルではなくソース ユニットのみを含めました。
こちらからダウンロードしてください (パスワードは stackoverflow です): http://www34.zippyshare.com/v/16401041/file.html
最終的に私の質問は次のとおりです。
- 正しい階層構造で XML に保存する方法。
- XML をロードし、ツリービューを保存前の状態に正確に再構築する方法。
どうもありがとう。