|
|
 |
 |
|
|
 |
 |
|
Join the Discussion
|
"Post your views, comments, questions and doubts to this article."
Discuss!
|
|
 |
 |
|
|
 |
 |
 |
The TTreeView Delphi component (located on the "Win32" component palette tab) represents a window that displays a hierarchical list of items. Each item (tree node) consists of a label and an optional bitmapped image (two to be precise).
XML gives developers the power to deliver structured data. A structure of an XML document is very similar to the structure of a tree view. In Delphi, the TXMLDocument (located on the "Internet" component palette tab) can be used to represent an XML document.
This article will show you techniques you can use to export tree view items to an XML file, and how to construct a tree view from an XML document.
If you need a powerful and transferable format for some kind of application configuration storage, which comes from a tree view, XML is a great choice, as you will see...
Saving TTreeView items to XML
First, we build a sample application hosting a TTreeView component, two ImageList components and one TXMLDocument component. One image list is associated with the Images property of a TreeView, another attached to the StateImages property (see: how to add check boxes and radio buttons to a tree view).
This is a screen shot of the application at run time (with "dummy" images for tree items). The Tree2XML procedure is used to save the tree view items to an XML document. Its only parameter is the reference to a TTreeView component we are saving to XML. The XML document has the same name as the application (of course, with the '.XML' as extension)
The procedure basically iterates through all TreeView items and for each item calls the ProcessTreeItem sub-procedure. The ProcessTreeItem is then recursively called for each tree node at the same level as the calling node. This recursive algorithm ensures all TreeView nodes are processed.
For each tree view item, an XML node (IXMLNode) is created with its attributes holding the values of Text, ImageIndex and StateIndex properties. Note that you could actually store any kind of tree node related value.
Once all the tree view items were processed the XML file is saved.
Note that the ProcessTreeItem procedure dynamically creates and manipulates a TXMLDocument (XMLDoc) component.
procedure Tree2XML(tree: TTreeView);
var
tn : TTreeNode;
XMLDoc : TXMLDocument;
iNode : IXMLNode;
procedure ProcessTreeItem(
tn : TTreeNode;
iNode : IXMLNode);
var
cNode : IXMLNode;
begin
if (tn = nil) then Exit;
cNode := iNode.AddChild('item');
cNode.Attributes['text'] := tn.Text;
cNode.Attributes['imageIndex'] := tn.ImageIndex;
cNode.Attributes['stateIndex'] := tn.StateIndex;
//child nodes
tn := tn.getFirstChild;
while tn <> nil do
begin
ProcessTreeItem(tn, cNode);
tn := tn.getNextSibling;
end;
end; (*ProcessTreeItem*)
begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
iNode := XMLDoc.AddChild('tree2xml');
iNode.Attributes['app'] := ParamStr(0);
tn := tree.TopItem;
while tn <> nil do
begin
ProcessTreeItem (tn, iNode);
tn := tn.getNextSibling;
end;
XMLDoc.SaveToFile(ChangeFileExt(ParamStr(0),'.XML'));
XMLDoc := nil;
end; (* Tree2XML *)
|
In real world scenarios, you would export your tree view to XML when the application gets closed. The sample application provided for download, uses the OnCloseQuery event of a form to ask the user whether the TreeView should be saved to an XML:
// tree is the name of the TTreeView component
procedure TForm1.FormCloseQuery(
Sender: TObject;
var CanClose: Boolean);
begin
case MessageDlg('Save tree items to XML?',
mtConfirmation,
[mbYes, mbNo, mbCancel], 0) of
mrYes:
Tree2XML(tree);
mrNo:
CanClose := True;
mrCancel:
CanClose := False;
end;
end;
|
Here's the resulting XML document.
Loading TTreeView items from XML
Once we have the XML representation of the tree view items, we can use it to populate the tree view. When the application starts, the XML2Tree procedure is called to construct the tree. The tree parameter is a reference to a TTreeView component we are populating; the XMLDoc parameter points to a TXMLDocument component. In this case we are using the TXMLDocument component dropped on a form.
procedure XML2Tree(
tree : TTreeView;
XMLDoc : TXMLDocument);
var
iNode : IXMLNode;
procedure ProcessNode(
Node : IXMLNode;
tn : TTreeNode);
var
cNode : IXMLNode;
begin
if Node = nil then Exit;
with Node do
begin
tn := tree.Items.AddChild(tn, Attributes['text']);
tn.ImageIndex := Integer(Attributes['imageIndex']);
tn.StateIndex := Integer(Attributes['stateIndex']);
end;
cNode := Node.ChildNodes.First;
while cNode <> nil do
begin
ProcessNode(cNode, tn);
cNode := cNode.NextSibling;
end;
end; (*ProcessNode*)
begin
tree.Items.Clear;
XMLDoc.FileName := ChangeFileExt(ParamStr(0),'.XML');
XMLDoc.Active := True;
iNode := XMLDoc.DocumentElement.ChildNodes.First;
while iNode <> nil do
begin
ProcessNode(iNode,nil);
iNode := iNode.NextSibling;
end;
XMLDoc.Active := False;
end;
|
The XML2Tree procedure basically operates on the same principles as the Tree2XML does. The code walks through the nodes of the XML, creates TTreeNode objects and adds them to the TreeView component.
That's it
To be honest, in the last couple of projects I've stopped using the Registry or INI files for storing a few pieces of application configuration data. XML seems much friendlier.
The full source code is available for download.
If you need any help with the code, do post your questions and/or comments to the Delphi Programming Forum.
|