笔记
很抱歉,这篇长篇文章,我认为最好尽可能多地提供信息,而不是在需要时填补空白。
请注意,尽管我也将其标记为 Delphi 并且拥有并仍在使用 Delphi XE 我现在使用 Lazarus 作为我的主要 IDE,但我根本买不起较新的 Delphi 版本,现在 Lazarus 变得更加稳定,这对我来说很有意义切换到拉撒路。
对于这个问题,我已经包含了一个带有项目源的 zip 附件,虽然它是用 Lazarus 编写的,但它确实有助于解决我的问题,因此第一段中的评论。
概述
关于这个问题,我有一个拥有多个类作为 TLists 的对象。
我在 Treeview 中表示这些数据,并且无法知道树中将存在多少级别和节点,因为它们是在运行时动态创建的。我设置的一个限制是顶级节点将被固定,这意味着它们不能被删除或重命名——这些就是我所说的 RootGroups。
Treeview 将填充项目和组,添加到 Treeview 的每个节点都将有自己的 Object 分配给数据以正确识别每个项目。我现在将展示一个示例屏幕截图,以便在继续之前给出一个更好的主意:
如您所见,我有两个最顶层的节点,Object1Root和Object2Root。如果您注意到右侧的按钮,它们允许将组和项目添加到 Treeview,但如果它们不属于 Treeview 的该部分,它们将被禁用。例如,您不能在Object1Root下添加Object2Group或Object2Item。
基本上,树视图中的所有内容都有自己的指向对象的指针。我从基础对象派生的每个对象。此基础对象具有存储它在 Treeview 中的位置的属性,如下所示:
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,然后为每个对象分配节点数据,例如父级、级别、索引等。基于第一个图像的输出 XML 文件如下所示:
注意: SomeVal 部分并不重要,因为我从来没有费心向对象写任何东西。
我真正应该做的是保存到 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 并将 Treeview 重建为保存前的样子。
非常感谢。