|
The C# Column
Creating UI for an XML document
There
are two purposes of this article. The first is to show how to work
with a tree control in .NET and the second, to create a user interface
for an XML document. To fulfill these purposes, we have created
a WinForm application that displays the elements and nodes of an
XML document in a tree view control.
We will first understand the structure of a tree view control.
The TreeView control displays tree items, called nodes, in a hierarchical manner.
A parent node contains child nodes. The child nodes can be parent nodes for
other nodes. Two child nodes having same parent node are called sibling nodes.
The first parent node of a tree is called the root node. There can be multiple
root nodes in a tree, just like a system has multiple root drives.
The nodes displayed in a tree are instances of the TreeNode class. Each TreeNode
has a Nodes collection stored in the TreeNodeCollection. This collection stores
the list of other TreeNodes, its children. The Parent property returns the reference
to the parent node.
Now, place a TextBox, Button, TreeView, Label and an ImageList
control on the form. Name the controls as listed in the following table.
| Control |
Name |
| TextBox |
txtfile |
| Button |
bload |
| TreeView |
xmltree |
| ImageList |
imglist |
| Label |
lblpath |
We will display different images for XML elements and nodes
in the tree control. For this, create four bitmap files. Add these files to
the Images collection of the ImageList control. The first two images are used
for elements and nodes, whereas, the next two images are used as selected images
for elements and nodes
The user should enter an XML file name in the text box and click the Load
button. This will display the XML document in the tree control. Add the Click
event handler for the Load button. This handler is given below.
private void bload_Click ( object sender, System.EventArgs
e )
{
try
{
XmlDocument
doc = new XmlDocument( ) ;
doc.Load
( txtfile.Text ) ;
xmltree.Nodes.Clear(
) ;
additem
( doc.DocumentElement, null ) ;
}
catch ( Exception e1 )
{
MessageBox.Show
( e1.Message ) ;
}
}
Here, we have loaded the document in memory by calling the Load( ) method of
the XmlDocument class. It may happen that the user first loads one document
and then another. In such a case we must delete the nodes of the first document
before adding new nodes to it. We have done so by calling the Clear( ) method
of the TreeNodeCollection class. We have accessed the collection using the Nodes
property of the TreeView class.
To add the new item, we have called the user-defined additem( ) method. We have
passed two parameters to itthe node of the XML document loaded in memory
as the first parameter and node of the tree control as the second parameter.
The root node in the document is represented by the DocumentElement property.
We have passed null as the tree controls node because there are no nodes
in the tree control yet.
We have written the code in the try-catch block because the Load( ) method throws
an exception if it fails, instead of returning an error value.
Lets write the additem( ) method.
public void additem ( XmlNode xnode, TreeNode tnode )
{
TreeNode
child = addnode ( xnode, tnode ) ;
if ( xnode.Attributes
!= null )
{
string
text ;
foreach
( XmlAttribute attr in xnode.Attributes )
{
text
= attr.Name + = + attr.Value ;
child.Nodes.Add ( new TreeNode ( text ) ) ;
}
}
if
( xnode.HasChildNodes )
{
foreach
( XmlNode node in xnode.ChildNodes )
additem
( node, child ) ;
}
}
The additem( ) method is used to traverse the document structure loaded in memory.
It would start traversing from the node that is passed to it in xnode. For the
first time, xnode will contain the root document node. From this method we have
called another user-defined method called addnode( ). The addnode( ) method
actually adds the XML node to the tree control at the appropriate place and
returns its reference. We have collected this reference in child. If the XML
node that has been added to the tree has attributes, we must add them to the
newly added tree node. To retrieve the attributes we have used the Attributes
property. It returns all the attributes of the node in a collection. We have
retrieved an attribute from collection in a foreach loop and added its name
and value to the tree node. For this, we have used the Add( ) method.
If the XML node has child nodes then this procedure should repeat for each child
node. We have checked whether the XML node has children or not using the HasChildNodes
property. Then, for each node we have called the additem( ) method recursively.
This time we are passing a reference to the child node as the first parameter
and a reference to the newly added tree node as the second parameter to the
additem( ) method.
The addnode( ) method is given below.
public TreeNode addnode ( XmlNode xnode, TreeNode tnode )
{
string
txt ;
TreeNode child = new TreeNode(
) ;
TreeNodeCollection tnodes ;
if ( tnode == null )
tnodes = xmltree.Nodes
;
else
tnodes =
tnode.Nodes ;
switch ( xnode.NodeType )
{
case
XmlNodeType.Element:
child
= new TreeNode ( xnode.Name ) ;
child.ImageIndex = 0
;
child.SelectedImageIndex
= 2 ;
tnodes.Add ( child )
;
break ;
case
XmlNodeType.Text:
txt
= xnode.Value ;
if ( txt.Length > 128 )
txt
= txt.Substring ( 0, 128 ) + ... ;
child = new TreeNode ( txt
) ;
child.ImageIndex = 1 ;
child.SelectedImageIndex =
3 ;
tnodes.Add ( child ) ;
break ;
}
return child ;
}
Let us now see the addnode( ) method. Here, firstly we have declared child as
a reference of type TreeNode and tnodes of type TreeNodeCollection. The TreeNodeCollection
object represents a collection of tree node objects. If the tree control is
empty we must add the XML node as the root node of the control. Otherwise we
must add the XML node as a child of tnode. We have achieved this by applying
an if condition on tnode.
We have checked the type of XML node in the switch-case block. If the node type
is an element, we have added its name to the tree node. Before adding, we have
created the new node and collected its reference in child. This node is then
added to the tree control. We have provided proper images using the ImageIndex
and SelectedImageIndex properties.
If the node type is text content, we must add its value to the tree node.
Before adding text content, we have checked whether its length exceeds 128.
If it does, we have extracted the first 128 characters and added ellipses (
)
to it indicating the incomplete string. We have then created a new node child
and added it to the tree control. Lastly, we have returned the reference to
the newly created node.
We have added a handler for the AfterSelect event of the TreeView control. This
event is thrown when tree item selection is changed. In this handler we have
obtained the path of the tree node and displayed it in the label.
private void xmltree_AfterSelect ( object sender, TreeViewEventArgs
e)
{
lblpath.Text = xmltree.SelectedNode.FullPath
;
}
We have obtained the currently selected tree node using the SelectedNode property.
The FullPath property of the TreeNode class returns the path of the node with
respect to the root node.

 |
Yashavant Kanetkar, one of
the first Express Computer columnists, is an established software
expert, speaker and author with several best-sellers to his
credit, including titles like “Let Us C” and the “Fundas” series.
Contact him at kanetkar@dcubesoft.com |
|