Сохранение и загрузка TreeView с использованием XML

Заметка

Заранее извините за длинный пост, хотя лучше разместить как можно больше информации, а не заполнять пробелы, когда это необходимо.

Обратите внимание, что хотя я пометил это как Delphi, так и сделаю собственное и все еще использую Delphi XE, я сейчас использую Lazarus в качестве своей основной IDE, я просто не могу позволить себе покупать более новые версии Delphi, и теперь Lazarus становится более стабильным, это имеет смысл для меня переключиться на Лазаря.

Для этого вопроса я включил zip-вложение с исходным кодом проекта, хотя написанный на Lazarus он действительно поможет с моим вопросом, поэтому и комментарии в первом абзаце.

обзор

На вопрос, у меня есть объект, который владеет несколькими классами как TLists.

Я представляю эти данные в виде дерева, и нет способа узнать, сколько уровней и узлов будет присутствовать в дереве, поскольку они динамически создаются во время выполнения. Одно ограничение, которое я установил, заключается в том, что узлы верхнего уровня будут фиксированными, то есть они не могут быть удалены или переименованы - это то, что я буду называть RootGroups.

Древовидное представление будет заполнено элементами и группами, каждому узлу, добавленному в Древовидное представление, будет присвоен собственный объект, назначенный данным для правильной идентификации каждого элемента. Я собираюсь показать пример скриншота сейчас, чтобы дать лучшую идею, прежде чем продолжить:

Как вы можете видеть, у меня есть два самых верхних узла,Object1Root а такжеObject2Root, Если вы заметили кнопки справа, они позволяют добавлять группы и элементы в древовидную структуру, но становятся недоступными, если непринадлежит этой части Treeview. Например, вы не можете добавитьObject2Group или жеObject2Item подObject1Root.

В основном все в древовидной структуре имеет свой собственный указатель на объект. Каждый объект, который я извлекаю из базового объекта. Этот базовый объект имеет свойства для хранения позиции, где он находится в древовидной структуре, например:

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, так как до сих пор с ним справляюсь, но я думаю, что вывод должен выглядеть примерно так: (написано в Блокноте)


  

  

Ответы на вопрос(2)

Ваш ответ на вопрос