Contents

Introduction

A recent post on a MS group regarding persisting TreeView data to file and apparent lack of VB.Net example lead me to write a solution as it was one of the first problems I faced as a developer and thought it would make for an interesting article for beginners. Additionally, the utilisation of serialisation to persist objects as Xml provides an introduction to a great ‘free’ way of storing data.

The Problem

The TreeView and TreeNode types have no intrinsic methods for persisting their data, neither are they serializable, the solution therefore is to write classes that can meditate between TreeView and file.

TreeView Structures

Firstly we need a couple of structures, one to represent the TreeView and another to represent a TreeNode. These structures need to duplicate the properties within these types that need to be persisted and provide methods to convert from the source objects and these structures.

TreeViewData Structure

This structure is used to represent the TreeView type and its properties in their simplest form:

<Serializable()>Public Structure TreeViewData
Public Nodes() As TreeNodeData
PublicSubNew(ByVal treeview As TreeView)
'Check to see if there are any root nodes in the TreeView
If treeview.Nodes.Count = 0ThenExitSub'Populate the Nodes array with child nodes
ReDim Nodes(treeview.Nodes.Count - 1)
For i AsInteger = 0To treeview.Nodes.Count - 1
Nodes(i) = New TreeNodeData(treeview.Nodes(i))
NextEndSubPublicSub PopulateTree(ByVal treeView As TreeView)
'Check to see if there are any root nodes in the TreeViewData
IfMe.Nodes IsNothingOrElseMe.Nodes.Length = 0ThenExitSub'Populate the TreeView with child nodes
treeView.BeginUpdate()
For i AsInteger = 0ToMe.Nodes.Length - 1
treeView.Nodes.Add(Me.Nodes(i).ToTreeNode)
Next
treeView.EndUpdate()
EndSubEndStructure

The only property within the TreeView that is represented by this structure is the Nodes collection as this is the only property that really needs to be persisted. Notice the constructer has a TreeView parameter, this allows the TreeViewData structure to be populated from the source TreeView in a single line of code:

Dim treeViewData1 asNew TreeViewData(MyTreeView)

Providing the TreeView Nodes collection contains one or more TreeNode object the constructer will adjust the size of the Nodes() array to match the size of the TreeView.Nodes collection and populate it with TreeNodeData representation of the root TreeNodes. The TreeNodeData structure will take care of populating its own hierarchy (

The PopulateTree method performs the reverse action to the constructor, by populating the specified TreeView with the contents of the TreeViewData instance. Notice in how the For loop is contained within BeginUpdate and EndUpdate statements, this prevents the TreeView from being redrawn each time a new Node is added, providing a smoother visual experience for the user, particularly on larger node hierarchies.

TreeNodeData Structure

This structure is used to represent the TreeNode class and its properties in their simplest form:

The TreeNode has a few more properties that need to be persisted compared to the TreeView, again the structure of the TreeNodeData instance is generated from the source object by passing it as a parameter in the constructor:

Because the Tag property can be any object, and this solution uses serialization (

Finally the structure contains the ToTreeNode function that returns a TreeNode object with its hierarchy populated from the TreeNodeData structure.

Properties to be persisted are directly mapped from the source TreeNode to the TreeNodeData instance with the exception of the Tag property:see below) to persist data we need to check that the object in the Tag can also be serialized, therefore we only map the Tag property if it is of a serializable type.see below).

Storing and Retrieving

These structures are all very well, but we’ve still not got a way of storing the TreeView to file. To achieve this goal we’ll use serialisation which basically converts objects that support it to and from structured Xml.

Notice that both the TreeViewData and TreeNodeData structures have the attribute <Serializable()> preceding their declaration, indicating the class can be serialized. All we have to do is provide a couple of methods to serialize and desterilize the structures, the first saves the structure to file:

This method accepts a couple of parameters; the TreeView to persist and the path to store the data. Notice the method is declared as a Shared, this means that an instance of its containing class does not need to be initiated before the method can be used (

Firstly we create an XmlSerializer that expects to be dealing with object of TreeViewData type, we create a file to save the Xml and an XmlTextWriter to write the serialized object to the file.

Here we create an instance of the TreeViewData structure and populate it from the desterilized Xml file, finally we call the PopulateTreeView method of the TreeViewData object to populate the specified TreeView. This takes the specified TreeView object, creates and populates a new instance of the TreeViewData class and writes it all to file. All we need to do then tidy up by closing the XmlWriter and file.

Bringing it all Together

Finally all this code can be brought into one containing class that can be used to persist the data of any TreeView, exposing the two Shared methods for simple reusability throughout your code. This TreeViewDataAccess class simply contains all the code listed above, and can be downloaded from the links at the top of this article.

To use the class anywhere in your code all you need is one line to save the TreeView data: