Click here to Skip to main content
11,719,185 members (86,545 online)
Click here to Skip to main content

Loading and Saving a TreeView control to an XML file using XmlTextWriter and XmlTextReader

, 17 Feb 2006 CPOL 143K 10.6K 126
Rate this:
Please Sign up or sign in to vote.
Demonstrates how to serialize and de-serialize the contents of System.Windows.Forms.TreeView control from an XML file using forward only, non-cached XmlTextReader and XmlTextWriter.

Introduction

The purpose of this article is to demonstrate the saving and loading of System.Windows.Forms.TreeView control from an XML file. XmlTextReader and XmlTextWriter of System.Xml namespace are used for reading and generating XML files respectively. It also demonstrates a simple XML file viewer using a TreeView control.

Getting started

The real functionality is enclosed in a class called TreeViewSerializer. It has two main responsibilities:

  1. Saving the TreeView to a specified XML file.
  2. Loading the TreeView from any specified XML file.

The structure of an XML file used for serializing a TreeView is quite simple. Following is a sample XML file included with the attached project:

<?xml version="1.0" encoding="us-ascii" ?> 
<TreeView>
   <node text="Asia" imageindex="0">
      <node text="China" imageindex="-1" tag="Largest Population">
          <node text="Beijing" imageindex="-1" /></node>
      <node text="Pakistan" imageindex="4" /> 
      <node text="India" imageindex="5" /> 
      <node text="Srilanka" imageindex="6" /> 
   </node>
   <node text="Europe" imageindex="1">
      <node text="Germany" imageindex="6" /> 
      </node>
   <node text="America" imageindex="2" /> 
   <node text="Africa" imageindex="3" /> 
</TreeView>

After the XML declaration, all the nodes are enclosed in a TreeView tag. The TreeView tag may contain multiple node tags. The node tag can also contain other node tags. Each node tag can have three attributes:

  1. Text
  2. ImageIndex
  3. Tag

I have serialized the above three attributes of System.Windows.Forms.TreeNode object, it can be easily extended to include other attributes.

XmlNodeTag, XmlNodeTextAtt, XmlNodeTagAtt and XmlNodeImageIndexAtt are the constants defined in TreeViewSerializer class:

// Xml tag for node, e.g. 'node' in case of <node></node>
private const string XmlNodeTag = "node";

// Xml attributes for node e.g. <node text="Asia" tag="" 
// imageindex="1"></node>
private const string XmlNodeTextAtt = "text";
private const string XmlNodeTagAtt = "tag";
private const string XmlNodeImageIndexAtt = "imageindex";

Loading TreeView from XML – Deserialization

The deserialization is performed by the DeserializeTreeView method which uses XmlTextReader to parse through the XML document and fill the TreeView object. Following is the definition of DeserializeTreeView method:

public void DeserializeTreeView(TreeView treeView, string fileName)
{
   XmlTextReader reader = null;
   try
   {
        // disabling re-drawing of treeview till all nodes are added
        treeView.BeginUpdate();    
        reader = new XmlTextReader(fileName);
        TreeNode parentNode = null;
        while (reader.Read())
        {
             if (reader.NodeType == XmlNodeType.Element)
             {      
                  if (reader.Name == XmlNodeTag)
                  {
                       TreeNode newNode = new TreeNode();
                       bool isEmptyElement = reader.IsEmptyElement;
                
                       // loading node attributes
                       int attributeCount = reader.AttributeCount;
                       if (attributeCount > 0)
                       {
                          for (int i = 0; i < attributeCount; i++)
                          {
                              reader.MoveToAttribute(i);
                              SetAttributeValue(newNode, 
                                           reader.Name, reader.Value);
                          }        
                       }
                       // add new node to Parent Node or TreeView
                       if(parentNode != null)
                          parentNode.Nodes.Add(newNode);
                       else
                          treeView.Nodes.Add(newNode);
                
                       // making current node 'ParentNode' if its not empty
                       if (!isEmptyElement)
                       {
                          parentNode = newNode;
                       }
                  }                          
             }
             // moving up to in TreeView if end tag is encountered
             else if (reader.NodeType == XmlNodeType.EndElement)
             {
                  if (reader.Name == XmlNodeTag)
                  {
                           parentNode = parentNode.Parent;
                  }
             }
             else if (reader.NodeType == XmlNodeType.XmlDeclaration)
             { 
                  //Ignore Xml Declaration                    
             }
             else if (reader.NodeType == XmlNodeType.None)
             {
                  return;
             }
             else if (reader.NodeType == XmlNodeType.Text)
             {
                  parentNode.Nodes.Add(reader.Value);
             }
    
        }
   }
   finally
   {
        // enabling redrawing of treeview after all nodes are added
        treeView.EndUpdate();      
        reader.Close(); 
   }
}

As XmlTextReader parses through the XML document, appropriate actions are taken depending on the NodeType. If the NodeType is Element, a new TreeNode is created and its properties are set using the XML node attributes. The ParentNode is set to the new TreeNode in case of non-empty elements so that its child nodes are deserialized. If an EndElement is encountered, the ParentNode is set to the parent of the current parent node indicating that all the child nodes of the current node are deserialized.

For setting the Text, Tag and ImageIndex properties of a TreeNode, the SetAttributeValue method is called. It has the following implementation:

/// <span class="code-SummaryComment"><summary>
</span>

Saving TreeView – Serialization

The SerializeTreeView saves the System.Windows.Forms.TreeView to the specified file. Following is the method definition:

public void SerializeTreeView(TreeView treeView, string fileName) 
  {
       XmlTextWriter textWriter = new XmlTextWriter(fileName, 
                                     System.Text.Encoding.ASCII);
       // writing the xml declaration tag
       textWriter.WriteStartDocument();
       //textWriter.WriteRaw("\r\n");
       // writing the main tag that encloses all node tags
       textWriter.WriteStartElement("TreeView");
       
       // save the nodes, recursive method
       SaveNodes(treeView.Nodes, textWriter);
       
       textWriter.WriteEndElement();
         
       textWriter.Close();
  }

The above code I guess is pretty much self explanatory. The SerializeTreeView method:

  1. Instantiates the XmlTextWriter, passing it the provided filename.
  2. XML declaration (<?xml version="1.0" encoding="us-ascii" ?>) is written to the stream.
  3. The TreeView tag is written to the stream.
  4. SaveNodes method is called. The TreeNode collection in a TreeView is passed to it, it saves all the nodes in a TreeView to the stream calling itself recursively. Its definition is produced below.
  5. The end tag of TreeView is written.
  6. And finally the stream is closed.

Following is the definition of SaveNodes method:

private void SaveNodes(TreeNodeCollection nodesCollection, 
   XmlTextWriter textWriter)
  {
       for(int i = 0; i < nodesCollection.Count; i++)
       {
            TreeNode node = nodesCollection[i];
            textWriter.WriteStartElement(XmlNodeTag);
            textWriter.WriteAttributeString(XmlNodeTextAtt, 
                                                       node.Text);
            textWriter.WriteAttributeString(
                XmlNodeImageIndexAtt, node.ImageIndex.ToString());
            if(node.Tag != null) 
                 textWriter.WriteAttributeString(XmlNodeTagAtt, 
                                             node.Tag.ToString());
            // add other node properties to serialize here  
            if (node.Nodes.Count > 0)
            {
                 SaveNodes(node.Nodes, textWriter);
            }     
            textWriter.WriteEndElement();
       }
  }

The SaveNodes method loops through the TreeNode collection, and writes the node tag and its attributes. If a node has child nodes then the method is called recursively. After the method returns, having written the child nodes to the stream, the node end tag is written.

XML File Viewer

There is another method in the TreeViewSerializer class called LoadXmlFileInTreeView. This can be used to view any XML document in the TreeView. The following screen shot displays our sample XML file loaded into the TreeView:

The code for loading an XML file is pretty much similar to the SerializeTreeView method. I am not including the code here for the sake of brevity. You can find it in the attached source code.

Demo application

A demo application is provided with the article as the driver of TreeViewSerializer functionality. It has three functions:

  • Save: save/serialize the TreeView to an XML file. A SaveFileDialog appears for specifying the file.
  • Load: load/deserialize the TreeView from an XML file.
  • View XML File: to view any XML file in the TreeView.

Notes

The XML document can also be manipulated using the DOM based XmlDocument and XmlNode classes. They are useful if we require searching and editing of XML document. In our case, XmlTextWriter and XmlTextReader are more efficient as they operate in a forward only, non-cached manner.

The generated XML file is not formatted by inserting a new line and tabs. Use textWriter.WriteRaw("\r\n"); at appropriate places in SerializeTreeView for this purpose. Obviously, you may use IE to view the formatted XML file. Smile | :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Syed Umar Anis
Software Developer (Senior)
United Arab Emirates United Arab Emirates

You may also be interested in...

Comments and Discussions

 
QuestionCreate Xml String without Save to file Pin
taqech@Gmail.com6-Mar-15 20:46
membertaqech@Gmail.com6-Mar-15 20:46 
AnswerRe: Create Xml String without Save to file Pin
Syed Umar Anis8-Mar-15 6:11
professionalSyed Umar Anis8-Mar-15 6:11 
QuestionFantastic Pin
Member 1047840626-Jan-14 0:48
memberMember 1047840626-Jan-14 0:48 
AnswerRe: Fantastic Pin
Syed Umar Anis26-Jan-14 2:26
memberSyed Umar Anis26-Jan-14 2:26 
AnswerRe: Fantastic Pin
Member 1047840626-Jan-14 21:55
memberMember 1047840626-Jan-14 21:55 
QuestionWhat about the Tag property? Pin
Mark F.20-Nov-13 17:45
memberMark F.20-Nov-13 17:45 
AnswerRe: What about the Tag property? Pin
Syed Umar Anis28-Nov-13 8:03
memberSyed Umar Anis28-Nov-13 8:03 
Question=D Pin
Member 1021732318-Aug-13 20:52
memberMember 1021732318-Aug-13 20:52 
AnswerRe: =D Pin
Syed Umar Anis19-Aug-13 2:07
memberSyed Umar Anis19-Aug-13 2:07 
QuestionJust what I needed! Pin
Alexander Grinin3-May-13 5:17
memberAlexander Grinin3-May-13 5:17 
AnswerRe: Just what I needed! Pin
Syed Umar Anis3-May-13 7:13
memberSyed Umar Anis3-May-13 7:13 
SuggestionGreat Job, but some minor modifications needed. Pin
Behzad Sedighzadeh7-Apr-13 6:55
memberBehzad Sedighzadeh7-Apr-13 6:55 
GeneralMy vote of 5 Pin
Chris Robert Mead4-Jul-12 7:19
memberChris Robert Mead4-Jul-12 7:19 
GeneralHow do I change the tag for the nodes - at each level? Pin
sjs197828-Jun-12 7:10
membersjs197828-Jun-12 7:10 
GeneralMy vote of 5 Pin
karthikin15-Jun-12 22:57
memberkarthikin15-Jun-12 22:57 
GeneralMy vote of 5 Pin
DuffmanLight31-Jan-12 13:09
memberDuffmanLight31-Jan-12 13:09 
GeneralExcellent time-saver Pin
Bill Hardwick8-Sep-11 0:36
memberBill Hardwick8-Sep-11 0:36 
QuestionThank youuu.. Great job :) Pin
catastrophic70728-Jun-11 3:56
membercatastrophic70728-Jun-11 3:56 
AnswerRe: Thank youuu.. Great job :) Pin
Syed Umar Anis28-Jul-11 0:42
memberSyed Umar Anis28-Jul-11 0:42 
GeneralGreat Pin
FrankBrummel7-May-11 10:51
memberFrankBrummel7-May-11 10:51 
GeneralAdding textWriter.Formatting = Formatting.Indented will help to have XML file more readable Pin
yuriyag3-Feb-11 6:55
memberyuriyag3-Feb-11 6:55 
GeneralRe: Adding textWriter.Formatting = Formatting.Indented will help to have XML file more readable Pin
Syed Umar Anis6-Feb-11 18:18
memberSyed Umar Anis6-Feb-11 18:18 
GeneralThanks!! Pin
yuriyag3-Feb-11 6:47
memberyuriyag3-Feb-11 6:47 
GeneralVery useful... Pin
ADLER15-Jan-10 8:08
memberADLER15-Jan-10 8:08 
GeneralReally Nice work !! Pin
damon883-Sep-09 19:45
memberdamon883-Sep-09 19:45 
GeneralTruely Amazing Pin
SalehJ16-Jul-09 1:09
memberSalehJ16-Jul-09 1:09 
GeneralAmazing [modified] Pin
MrWolfy21-Sep-08 10:27
memberMrWolfy21-Sep-08 10:27 
GeneralRe: Amazing Pin
ckarky17-Oct-08 7:08
memberckarky17-Oct-08 7:08 
GeneralGREAT !!!! Pin
SkyStrike23-Jun-08 17:03
memberSkyStrike23-Jun-08 17:03 
Generaluse switch and case Pin
Lew Wadoo28-Oct-07 8:12
memberLew Wadoo28-Oct-07 8:12 
GeneralBest Pin
sandeepbharati23-Oct-07 7:38
membersandeepbharati23-Oct-07 7:38 
General100 % clean usage Pin
jonMcCoy21-Aug-07 10:13
memberjonMcCoy21-Aug-07 10:13 
GeneralBug in Code Pin
brian252-Jul-07 6:51
memberbrian252-Jul-07 6:51 
GeneralGREAT ! Pin
BCBCBCBC6-Jun-07 1:42
memberBCBCBCBC6-Jun-07 1:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150901.1 | Last Updated 17 Feb 2006
Article Copyright 2006 by Syed Umar Anis
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid