Introduction
This article will demonstrate how to populate a Windows Forms TreeView
control from an XML file, as well as provides two methods to serialize the TreeView
back to XML.
Background
There are probably a thousand ways out on the 'net to do this. I know I've downloaded control after control, and I've seen hundreds of different techniques for doing this. This is, to date, the simplest way of doing this I've come across, and it doesn't require adding any controls to your project. You only need a couple of methods, and you're ready to go. Since there tend to be discrepancies on "best practices" with regards to XML serialization, I've included two common, and efficient methods for doing so.
Getting Started
If you download the working sample, you'll be able to immediately run the application and see how the methods work. I've included an examples.xml file for use in testing the application. Keep in mind that I've only done the barest of exception handling in the demo project. You'll want to ensure you include the following references in your application:
using System.Xml;
using System.Text;
using System.IO;
De-Serializing XML
XML is a great format. I mean, it's just text, after all, put together in a hierarchical fashion. .NET has been helpful (albeit a bit over-heady) in providing methods for loading and iterating through XML documents. The following methods will open an XML file, and populate each node into a TreeView
control:
private void populateTreeview()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Open XML Document";
dlg.Filter = "XML Files (*.xml)|*.xml";
dlg.FileName = Application.StartupPath + "\\..\\..\\example.xml";
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
this.Cursor = Cursors.WaitCursor;
XmlDocument xDoc = new XmlDocument();
xDoc.Load(dlg.FileName);
treeView1.Nodes.Clear();
treeView1.Nodes.Add(new
TreeNode(xDoc.DocumentElement.Name));
TreeNode tNode = new TreeNode();
tNode = (TreeNode)treeView1.Nodes[0];
addTreeNode(xDoc.DocumentElement, tNode);
treeView1.ExpandAll();
}
catch(XmlException xExc)
{
MessageBox.Show(xExc.Message);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
this.Cursor = Cursors.Default;
}
}
}
private void addTreeNode(XmlNode xmlNode, TreeNode treeNode)
{
XmlNode xNode;
TreeNode tNode;
XmlNodeList xNodeList;
if (xmlNode.HasChildNodes)
{
xNodeList = xmlNode.ChildNodes;
for(int x=0; x<=xNodeList.Count-1; x++)
{
xNode = xmlNode.ChildNodes[x];
treeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = treeNode.Nodes[x];
addTreeNode(xNode, tNode);
}
}
else
treeNode.Text = xmlNode.OuterXml.Trim();
}
That's all it takes to load an XML file into a TreeView
. The form will look something like this:

While I'd like to take full credit for it, I can't, since MSDN has a similar example that does the same thing. However, the two methods below for serializing the XML back to file format are all mine.
Serializing the TreeView
Using a StreamWriter
There are purists out there who won't want to use this method. .NET provides developers with an XmlTextWriter
which has methods inside that will dump formatted XML tags to a file. The bottom line is, it's all text, folks. How it gets there isn't as important as the fact that it got there. So, that in mind, I've provided methods for using a Streamwriter
here, and below, methods for using an XmlTextWriter
. Honestly, there is probably less actual code required to use the XmlTextWriter
, so I suggest using whichever you're most comfortable with.
private StreamWriter sr;
public void exportToXml(TreeView tv, string filename)
{
sr = new StreamWriter(filename, false, System.Text.Encoding.UTF8);
sr.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
sr.WriteLine("<" + treeView1.Nodes[0].Text + ">");
foreach (TreeNode node in tv.Nodes)
{
saveNode(node.Nodes);
}
sr.WriteLine("</" + treeView1.Nodes[0].Text + ">");
sr.Close();
}
private void saveNode(TreeNodeCollection tnc)
{
foreach (TreeNode node in tnc)
{
if (node.Nodes.Count > 0)
{
sr.WriteLine("<" + node.Text + ">");
saveNode(node.Nodes);
sr.WriteLine("</" + node.Text + ">");
}
else
sr.WriteLine(node.Text);
}
}
Using an XmlTextWriter
The following methods do exactly the same thing as above, only using an XmlTextWriter
instead of a StreamWriter
:
private XmlTextWriter xr;
public void exportToXml2(TreeView tv, string filename)
{
xr = new XmlTextWriter(filename, System.Text.Encoding.UTF8);
xr.WriteStartDocument();
xr.WriteStartElement(treeView1.Nodes[0].Text);
foreach (TreeNode node in tv.Nodes)
{
saveNode2(node.Nodes);
}
xr.WriteEndElement();
xr.Close();
}
private void saveNode2(TreeNodeCollection tnc)
{
foreach (TreeNode node in tnc)
{
if (node.Nodes.Count > 0)
{
xr.WriteStartElement(node.Text);
saveNode2(node.Nodes);
xr.WriteEndElement();
}
else
{
xr.WriteString(node.Text);
}
}
}
That's all there is to it.
Points of Interest
The methods I used above are barebones. What I mean by this is that no attributes will be saved during serialization, only node names and text. This is rather easy to overcome, but you'll need to modify the serialization a bit to allow it to do so. This is probably most easily done using the XmlTextWriter
serialization methods.