将列表框数据保存到XML?

时间:2011-11-09 23:23:48

标签: xml delphi pointers listbox

我有2个列表框,第一个列表框存储每个项目Object属性的数据指针(由我编写的自定义类定义)。每当我从此列表框中选择一个项目时,我会通过访问存储在第一个列表框中的一些数据来填充第二个列表框。

这一切都很好,但现在我需要知道如何将列表框保存和恢复为XML。

如果有人可以提供示例或协助我编写代码来执行此操作,我将不胜感激。

以下是一些示例代码,用于说明如何创建和访问数据:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    ListBox2: TListBox;
    cmdAdd: TButton;
    txtValue1: TEdit;
    txtValue2: TEdit;
    procedure cmdAddClick(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TMyData = class(TObject)
  private
    FValue1: String;
    FValue2: String;
  public
    constructor Create(Value1, Value2: String);

    property Value1: String read FValue1 write FValue1;
    property Value2: String read FValue2 write FValue2;
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyData }

constructor TMyData.Create(Value1, Value2: String);
begin
  inherited Create;

  FValue1:= Value1;
  FValue2:= Value2;
end;

procedure TForm1.cmdAddClick(Sender: TObject);
var
  Obj: TMyData;
begin
  Obj:= TMyData.Create(txtValue1.Text, txtValue2.Text);
  Listbox1.AddItem(txtValue1.Text, Obj);
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  Obj: TMyData;
begin
  ListBox2.Items.Clear;

  Obj:= ListBox1.Items.Objects[ListBox1.ItemIndex] as TMyData;
  ListBox2.Items.Add(Obj.Value2);
end;

end.

1 个答案:

答案 0 :(得分:6)

  

tl; dr:使用 XML数据绑定向导创建用于处理特定XML文件的接口,étvoila。

实现此目的最简单的方法是从XML文件开始。例如,按如下方式构建它:

<?xml version="1.0"?>
<masteritems>
    <masteritem>
        <name>Caption1</name>
        <value>123456</value>
        <childitems>
            <childitem>
                <name>Caption1.1</name>
                <value>23452</value>
            </childitem>
            <childitem>
                <name>Caption1.2</name>
                <value>65465</value>
            </childitem>
        </childitems>
    </masteritem>
    <masteritem>
        ...
    </masteritem>
</masteritems>

接下来,使用 XML数据绑定向导为此类型的XML文件创建一个接口单元,请参阅文件&gt;新&gt;其他&gt;新&gt; XML数据绑定。根据需要调整,但只需通过单击“确定”传递每个向导页面,默认情况下工作正常。 (请注意,其他Delphi版本的默认设置可能与我的不同。)虽然我个人想要摆脱的一件事是每种接口类型的“Type”后缀。 (以及类类型名称,但这不是向导中的选项,因此您可以手动执行此操作。)

现在,要加载和操作此XML文件:

uses
  Classes, Controls, Forms, StdCtrls,
  Test, xmldom, XMLIntf, msxmldom, XMLDoc;

type
  TForm2 = class(TForm)
    ListBox1: TListBox;
    ListBox2: TListBox;
    XMLDocument1: TXMLDocument; { See tab 'Internet' on component palette }
    SaveButton: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure SaveButtonClick(Sender: TObject);
  private
    function CurrentMasterItem: IXMLMasterItem;
  end;

...

function TForm2.CurrentMasterItem: IXMLMasterItem;
var
  MasterItems: IXMLMasterItems;
  I: Integer;
begin
  MasterItems := GetMasterItems(XMLDocument1);
  for I := 0 to MasterItems.Count - 1 do
  begin
    Result := MasterItems.Masteritem[I];
    if Result.Name = ListBox1.Items[ListBox1.ItemIndex] then
      Break;
  end;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
  MasterItems: IXMLMasterItems;
  I: Integer;
begin
  XMLDocument1.FileName := 'Test.xml';
  XMLDocument1.NodeIndentStr := '<tab>';
  MasterItems := GetMasterItems(XMLDocument1);
  for I := 0 to MasterItems.Count - 1 do
    ListBox1.Items.Add(MasterItems[I].Name);
  XMLDocument1.Active := False;
end;

procedure TForm2.ListBox1Click(Sender: TObject);
var
  ChildItems: IXMLChildItems;
  I: Integer;
begin
  if ListBox1.ItemIndex > -1 then
  begin
    ChildItems := CurrentMasterItem.Childitems;
    ListBox2.Clear;
    for I := 0 to ChildItems.Count - 1 do
      ListBox2.Items.AddObject(ChildItems[I].Name,
        TObject(ChildItems[I].Value));
    XMLDocument1.Active := False;
  end;
end;

procedure TForm2.SaveButtonClick(Sender: TObject);
var
  ChildItems: IXMLChildItems;
  ChildItem: IXMLChildItem;
  I: Integer;
begin
  if ListBox1.ItemIndex > -1 then
  begin
    ListBox2.Items.AddObject('New item', TObject(543223));
    ChildItems := CurrentMasterItem.Childitems;
    ChildItems.Clear;
    for I := 0 to ListBox2.Count - 1 do
    begin
      ChildItem := ChildItems.Add;
      ChildItem.Name := ListBox2.Items[I];
      ChildItem.Value := Integer(ListBox2.Items.Objects[I]);
    end;
    XMLDocument1.SaveToFile(XMLDocument1.FileName);
    XMLDocument1.Active := False;
  end;
end;

更新:这是向导在此处创建的单位:

{*********************************************************}
{                                                         }
{                    XML Data Binding                     }
{                                                         }
{         Generated on: 10-11-2011 23:25:30               }
{       Generated from: H:\Delphi\Test\XMLTest\Test.xml   }
{   Settings stored in: H:\Delphi\Test\XMLTest\Test.xdb   }
{                                                         }
{*********************************************************}

unit Test;

interface

uses xmldom, XMLDoc, XMLIntf;

type

{ Forward Decls }

  IXMLMasterItems = interface;
  IXMLMasterItem = interface;
  IXMLChildItems = interface;
  IXMLChildItem = interface;

{ IXMLMasterItems }

  IXMLMasterItems = interface(IXMLNodeCollection)
    ['{ACA35986-053A-40AE-92E8-2044BC5DADC6}']
    { Property Accessors }
    function Get_Masteritem(Index: Integer): IXMLMasterItem;
    { Methods & Properties }
    function Add: IXMLMasterItem;
    function Insert(const Index: Integer): IXMLMasterItem;
    property Masteritem[Index: Integer]: IXMLMasterItem
      read Get_Masteritem; default;
  end;

{ IXMLMasterItem }

  IXMLMasterItem = interface(IXMLNode)
    ['{E6481675-AE5B-4166-A977-CA29EC97B78D}']
    { Property Accessors }
    function Get_Name: WideString;
    function Get_Value: Integer;
    function Get_Childitems: IXMLChildItems;
    procedure Set_Name(Value: WideString);
    procedure Set_Value(Value: Integer);
    { Methods & Properties }
    property Name: WideString read Get_Name write Set_Name;
    property Value: Integer read Get_Value write Set_Value;
    property Childitems: IXMLChildItems read Get_Childitems;
  end;

{ IXMLChildItems }

  IXMLChildItems = interface(IXMLNodeCollection)
    ['{CD16D91C-30E5-45A1-AAA1-1C518C84EA5B}']
    { Property Accessors }
    function Get_Childitem(Index: Integer): IXMLChildItem;
    { Methods & Properties }
    function Add: IXMLChildItem;
    function Insert(const Index: Integer): IXMLChildItem;
    property Childitem[Index: Integer]: IXMLChildItem
      read Get_Childitem; default;
  end;

{ IXMLChildItem }

  IXMLChildItem = interface(IXMLNode)
    ['{F7399037-A33F-4E43-ADF9-000EAD71B418}']
    { Property Accessors }
    function Get_Name: WideString;
    function Get_Value: Integer;
    procedure Set_Name(Value: WideString);
    procedure Set_Value(Value: Integer);
    { Methods & Properties }
    property Name: WideString read Get_Name write Set_Name;
    property Value: Integer read Get_Value write Set_Value;
  end;

{ Forward Decls }

  TXMLMasteritemsType = class;
  TXMLMasteritemType = class;
  TXMLChilditemsType = class;
  TXMLChilditemType = class;

{ TXMLMasteritemsType }

  TXMLMasteritemsType = class(TXMLNodeCollection, IXMLMasterItems)
  protected
    { IXMLMasterItems }
    function Get_Masteritem(Index: Integer): IXMLMasterItem;
    function Add: IXMLMasterItem;
    function Insert(const Index: Integer): IXMLMasterItem;
  public
    procedure AfterConstruction; override;
  end;

{ TXMLMasteritemType }

  TXMLMasteritemType = class(TXMLNode, IXMLMasterItem)
  protected
    { IXMLMasterItem }
    function Get_Name: WideString;
    function Get_Value: Integer;
    function Get_Childitems: IXMLChildItems;
    procedure Set_Name(Value: WideString);
    procedure Set_Value(Value: Integer);
  public
    procedure AfterConstruction; override;
  end;

{ TXMLChilditemsType }

  TXMLChilditemsType = class(TXMLNodeCollection, IXMLChildItems)
  protected
    { IXMLChildItems }
    function Get_Childitem(Index: Integer): IXMLChildItem;
    function Add: IXMLChildItem;
    function Insert(const Index: Integer): IXMLChildItem;
  public
    procedure AfterConstruction; override;
  end;

{ TXMLChilditemType }

  TXMLChilditemType = class(TXMLNode, IXMLChildItem)
  protected
    { IXMLChildItem }
    function Get_Name: WideString;
    function Get_Value: Integer;
    procedure Set_Name(Value: WideString);
    procedure Set_Value(Value: Integer);
  end;

{ Global Functions }

function Getmasteritems(Doc: IXMLDocument): IXMLMasterItems;
function Loadmasteritems(const FileName: WideString): IXMLMasterItems;
function Newmasteritems: IXMLMasterItems;

const
  TargetNamespace = '';

implementation

{ Global Functions }

function Getmasteritems(Doc: IXMLDocument): IXMLMasterItems;
begin
  Result := Doc.GetDocBinding('masteritems',
    TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;

function Loadmasteritems(const FileName: WideString): IXMLMasterItems;
begin
  Result := LoadXMLDocument(FileName).GetDocBinding('masteritems',
    TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;

function Newmasteritems: IXMLMasterItems;
begin
  Result := NewXMLDocument.GetDocBinding('masteritems',
    TXMLMasteritemsType, TargetNamespace) as IXMLMasterItems;
end;

{ TXMLMasteritemsType }

procedure TXMLMasteritemsType.AfterConstruction;
begin
  RegisterChildNode('masteritem', TXMLMasteritemType);
  ItemTag := 'masteritem';
  ItemInterface := IXMLMasterItem;
  inherited;
end;

function TXMLMasteritemsType.Get_Masteritem(Index: Integer): IXMLMasterItem;
begin
  Result := List[Index] as IXMLMasterItem;
end;

function TXMLMasteritemsType.Add: IXMLMasterItem;
begin
  Result := AddItem(-1) as IXMLMasterItem;
end;

function TXMLMasteritemsType.Insert(const Index: Integer): IXMLMasterItem;
begin
  Result := AddItem(Index) as IXMLMasterItem;
end;

{ TXMLMasteritemType }

procedure TXMLMasteritemType.AfterConstruction;
begin
  RegisterChildNode('childitems', TXMLChilditemsType);
  inherited;
end;

function TXMLMasteritemType.Get_Name: WideString;
begin
  Result := ChildNodes['name'].Text;
end;

procedure TXMLMasteritemType.Set_Name(Value: WideString);
begin
  ChildNodes['name'].NodeValue := Value;
end;

function TXMLMasteritemType.Get_Value: Integer;
begin
  Result := ChildNodes['value'].NodeValue;
end;

procedure TXMLMasteritemType.Set_Value(Value: Integer);
begin
  ChildNodes['value'].NodeValue := Value;
end;

function TXMLMasteritemType.Get_Childitems: IXMLChildItems;
begin
  Result := ChildNodes['childitems'] as IXMLChildItems;
end;

{ TXMLChilditemsType }

procedure TXMLChilditemsType.AfterConstruction;
begin
  RegisterChildNode('childitem', TXMLChilditemType);
  ItemTag := 'childitem';
  ItemInterface := IXMLChildItem;
  inherited;
end;

function TXMLChilditemsType.Get_Childitem(Index: Integer): IXMLChildItem;
begin
  Result := List[Index] as IXMLChildItem;
end;

function TXMLChilditemsType.Add: IXMLChildItem;
begin
  Result := AddItem(-1) as IXMLChildItem;
end;

function TXMLChilditemsType.Insert(const Index: Integer): IXMLChildItem;
begin
  Result := AddItem(Index) as IXMLChildItem;
end;

{ TXMLChilditemType }

function TXMLChilditemType.Get_Name: WideString;
begin
  Result := ChildNodes['name'].Text;
end;

procedure TXMLChilditemType.Set_Name(Value: WideString);
begin
  ChildNodes['name'].NodeValue := Value;
end;

function TXMLChilditemType.Get_Value: Integer;
begin
  Result := ChildNodes['value'].NodeValue;
end;

procedure TXMLChilditemType.Set_Value(Value: Integer);
begin
  ChildNodes['value'].NodeValue := Value;
end;

end.