|
There are two purposes of this article. First, to show how to work with a tree control in .NET and 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.
Firstly we would 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 control as shown in the following table.
| Control |
Name |
| TextBox |
txtfile |
| Button |
bload |
| TreeView |
xmltree |
| ImageList |
imglist |
| Label |
lblpath |
We would 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 would be used for elements and nodes, whereas, next two images would be 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 would 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 would first load one document and then another. In such case, we must delete the nodes of 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 it—the node of the XML document loaded in memory as first parameter and node of the tree control as second parameter. The root node in the document is represented by the
DocumentElement property. We have passed null as the tree control’s node because there are no nodes in the tree control yet.
We have written the code in try-catch block because the Load( ) method throws an exception if it fails instead of returning an error value.
Let’s 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 would 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 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 reference to the child node as first parameter and 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 if condition on tnode.
We have checked the type of XML node in the switch-case block. If the node type is 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 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 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.
|