From time to time I need to spit out the public properties of an object for various reasons. A typical use would be to show user friendly results from a web service that returns a complex object. There could be tons of other uses! After doing this a few times, I finially decided to post this so I can always reference it. Anytime I do any recursive methods, it always takes me a couple of tweaks before getting it right.
The idea is that I have a custom object that I need to spin through to populate a TreeView. I created a couple of simple methods to do such. I though about using Reflection, but my method starting getting larger and larger because I was having to put in special code to handle certain Types (i.e. String, ICollection, etc). Since my typical Use Case was to spit out the results of a complex object returned from a ASMX or WCF service, I decided to go the Serialize route. My DTO class was typically already decorated with the [Serializable] attribute, if not, it was simple enought to add.
So first we serialize the object into a string of XML, then stuff that into a XmlDocument. Then you can loop through the elements while creating each TreeViewNode. That’s it!
public void PopulateTreeView(object obj, TreeView tv)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
System.Text.StringBuilder sb = new System.Text.StringBuilder(); // StringBuilder to hold the XML
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb))
{
serializer.Serialize(writer, obj); // Serialize the object to XML
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
xDoc.LoadXml(sb.ToString()); // Shove it in a XmlDocument
tv.Nodes.Add(PopulateNode(xDoc)); // Add the Nodes to the TreeView
}
}
public TreeNode PopulateNode(System.Xml.XmlNode node)
{
TreeNode treenode = new TreeNode(node.Name); // Add the Name to the Node
if (node.ChildNodes.Count == 1) //Prevents ParentNode from displaying all of the InnerText
treenode.Text += "=" + node.InnerText; // If only 1 ChildNode then add the InnerText
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i].HasChildNodes)
{
treenode.ChildNodes.Add(PopulateNode(node.ChildNodes[i]));
}
}
return treenode;
}
Then call the method to populate where “customObject” is the object you want displayed in your TreeView:
PopulateTreeView(customObject, TreeView1);





#1 by Andre Brus on February 2, 2011 - 3:47 am
Hello Eric,
Ik saw your excellent example of “Populate TreeView From Custom Object Using Serializer”.
It seems to work well for my custom business objects, apart from 1 thing: when a field in my custom business objects has a value of NULL, it isn’t shown AT ALL in the treeview… It is just skipped. I would have expected/liked to see it in the treeview, shown as something like (for a NULL zipcode):
Street: Abbey Road
ZipCode: n/a
Housenumber: 13
Do you have an addition for your code to make this possible?
Thanks & Kind Regards, Andre Brus, Holland.
#2 by Eric on February 3, 2011 - 3:42 pm
Hello Andre,
There are two issues that is causing the NULL properties to not show up. The first is that by default the XmlSerializer will not serialize a null value. You can force it to do so by decorating your property with XmlElement(IsNullalble=true) attribute:
[System.Xml.Serialization.XmlElement(IsNullable = true)]public string NullableValueHere { get; set; }
That alone won’t fix your problem. We also need to tweak the code to check for “null” value in the xml. The XmlSerializer will add the attribute “xsi:nil=true” to the element. So we can look for that:
public TreeNode PopulateNode(System.Xml.XmlNode node){
TreeNode treenode = new TreeNode(node.Name); // Add the Name to the Node
if (node.ChildNodes.Count == 1) //Prevents ParentNode from displaying all of the InnerText
treenode.Text += "=" + node.InnerText; // If only 1 ChildNode then add the InnerText
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i].HasChildNodes || IsNull(node.ChildNodes[i]))
{
treenode.ChildNodes.Add(PopulateNode(node.ChildNodes[i]));
}
}
return treenode;
}
public bool IsNull(System.Xml.XmlNode node)
{
if (node.Attributes != null)
{
for (int i = 0; i < node.Attributes.Count; i++)
{
if (node.Attributes[i].Name == "xsi:nil")
{
return Convert.ToBoolean(node.Attributes[i].Value);
}
}
}
return false;
}
-----------------------------------
You can try that out and see if it works for you. I didn't fully test that code...and maybe it could be written better...but I think it will do what you are needing it to do.