C#: How to Display object hierarchy in TreeView using reflection
How to recursivley load a WinForm treeView of an object using reflection. I built this as a re-usable method so that I could look at the master-child relationships of an object. I also wanted to display the values of those objects. I can then use this to look at any type of object without hard-coding anything.
I could have used a 3rd party component, but until we have the budget to implement something like Infragistics, I just wanted to see my values rendered. And with a schema that is enormous, this can be extremely useful.
private void BindToTree(object data, Type t1)
{
TreeNode node = null;
if (t1.IsArray)
{
// Convert object into an array to traverse
IEnumerable arr = (IEnumerable)Convert.ChangeType(data, t1);
if (arr != null)
{
foreach (object element in arr)
{
node = new TreeNode(GetName(element.GetType()));
BuildNode(element, element.GetType(), ref node);
this.treeView1.Nodes.Add(node);
}
}
}
else
{
node = new TreeNode(GetName(t1));
BuildNode(data, t1, ref node);
this.treeView1.Nodes.Add(node);
}
}
private void BuildNode(object data, Type t1, ref TreeNode parentNode)
{
string currentElement = string.Empty;
try
{
//**************************************************
if (data == null)
return;
TreeNode childMain = null;
TreeNode childProp = null;
object value = null;
if (t1.IsArray)
{
//*****************************************
// Convert object into an array to traverse
IEnumerable arr = (IEnumerable)Convert.ChangeType(data, t1);
if (arr != null)
{
childMain = new TreeNode(string.Format("{0}", GetName(t1)));
foreach (object element in arr)
{
BuildNode(element, element.GetType(), ref childMain);
parentNode.Nodes.Add(childMain);
}
}
}
else
{
//*****************************************
// Now, let's look to build some nodes
if (t1 == typeof(String) || data is Enum)
{
// Part of a collection perhaps? ******
childMain = new TreeNode(string.Format("{0}", data.ToString()));
parentNode.Nodes.Add(childMain);
}
else
{
// Let's look at the properties *******
// Look at properties
PropertyInfo[] props = t1.GetProperties();
foreach (PropertyInfo prop in props)
{
if (!prop.Name.StartsWith("ExtensionData"))
{
// For exceptions
currentElement = GetName(t1) + "." + prop.Name;
// Property value
value = prop.GetValue(data, null);
if (prop.Name.EndsWith("PrimaryID"))
parentNode.Text += string.Format(" - [{0}]", value);
// Property has value, Or more children
if (prop.PropertyType.IsClass && prop.PropertyType != typeof(String))
{
// Child has children of its own
childMain = new TreeNode(string.Format("{0}", prop.Name));
// Recurse
object child_object = Convert.ChangeType(value, prop.PropertyType);
BuildNode(child_object, prop.PropertyType, ref childMain);
// Add the child with children
parentNode.Nodes.Add(childMain);
}
else
{
// Set the value
childProp = new TreeNode(string.Format("{0} = [{1}]",
prop.Name, ((value != null) ? value.ToString() : "NULL")));
// Add the child property
parentNode.Nodes.Add(childProp);
}
}
//loop
}
}
}
}
catch (Exception ex)
{
throw new Exception(currentElement, ex);
}
}
private string GetName(Type t)
{
string result = t.ToString();
if (result.Contains("."))
result = result.Substring(result.LastIndexOf(".") + 1);
if (result.EndsWith("[]"))
result = result.Substring(0, result.Length - 2);
return result;
}
keywords: recursion, reflection, recurse, C#, Windows Forms
Monday, July 07, 2008 12:22:05 PM