binaryBigInt binaryBigInt - 3 months ago 19
C# Question

C# - How to map object structure to a TreeView?

i would like to map the structure of an object to a TreeView. The object itself consists of

Dictionary<string,object>
. The problem for me now is that there is no consistency in how deep the structure can be because every
object
can be another dictionary (or just a text). For example, this is how one object could look like:
One Object

I know that i need some kind of recursion but i am not sure how i could map that to a tree view?
This is my current code:

Dictionary<string, object> dict = (Dictionary<string, object>)e.Node.Tag; //dict is the object
foreach(KeyValuePair<string,object> kvp in dict)
{
if(kvp.Key != "icon" && kvp.Key != "typeLine")
{

}
}


Any help is very much appreciated!

Edit: Sometimes the object of the KeyValuePair isn't another dictionary but just an array of objects (i dont't know why that is). It looks impossible, at least to me, to map that strange assembly of data to a treeview. Here is a picture about what i mean:

enter image description here

Edit(2): Okay, i think i finally got it working with this slightly modified function from Matthys:

private TreeNode[] RecurseTree(Dictionary<string, object> dic)
{
List<TreeNode> branch = new List<TreeNode>();

foreach (KeyValuePair<string, object> kvp in dic)
{
TreeNode twig = new TreeNode(kvp.Key);
if (kvp.Value is string || kvp.Value is bool || kvp.Value is int)
{
twig.Nodes.Add(new TreeNode(kvp.Value.ToString()));
}
else if (kvp.Value is Dictionary<string, object>)
{
twig.Nodes.AddRange(RecurseTree((Dictionary<string, object>)kvp.Value));
}
else
{
IEnumerable enumerable = (kvp.Value as IEnumerable);
if (enumerable != null)
{
foreach (var item in enumerable)
{
if (item is string || item is bool || item is int)
{
twig.Nodes.Add(new TreeNode(item.ToString()));
}
else if (item is Dictionary<string, object>)
{
twig.Nodes.AddRange(RecurseTree((Dictionary<string, object>)item));
}
else
{
IEnumerable en = (item as IEnumerable);
foreach(var i in en)
twig.Nodes.Add(new TreeNode(i.ToString()));
}
}
}
}
branch.Add(twig);
}

return branch.ToArray();
}

Answer

Try something like this:

private TreeNode[] RecurseTree(Dictionary<string, object> dic)
{
    List<TreeNode> branch = new List<TreeNode>();

    foreach (KeyValuePair<string, object> kvp in dic)
    {
        TreeNode twig = new TreeNode(kvp.Key);
        if (kvp.Value is string)
        {
            twig.Nodes.Add(new TreeNode(kvp.Value.ToString()));
        }
        else if (kvp.Value is Dictionary<string, object>)
        {
            twig.Nodes.AddRange(RecurseTree((Dictionary<string, object>)kvp.Value));
        }
        else
        {
            IEnumerable enumerable = (kvp.Value as IEnumerable);
            if(enumerable != null)
            {
                foreach(var item in enumerable)
                {
                    if (item is string)
                    {
                        twig.Nodes.Add(new TreeNode(item.ToString()));
                    }
                    else if (item is Dictionary<string,object>)
                    {
                        twig.Nodes.AddRange(RecurseTree((Dictionary<string, object>)item));
                    }
                }
            }
        }
        branch.Add(twig);
    }

    return branch.ToArray();
}

Then call it like this:

 treeView1.Nodes.AddRange(RecurseTree(YourDictionaryObject));

I tested this code as follows:

        Dictionary<string, object> a = new Dictionary<string, object>();
        Dictionary<string, object> b = new Dictionary<string, object>();
        Dictionary<string, object> c = new Dictionary<string, object>();
        Dictionary<string, object> d = new Dictionary<string, object>();
        Dictionary<string, object> h = new Dictionary<string, object>();
        Dictionary<string, object> f = new Dictionary<string, object>();
        Dictionary<string, object> g = new Dictionary<string, object>();
        Dictionary<string, object> i = new Dictionary<string, object>();
        object[] arrayOfObjects = {"This","is","an","array","of","objects", i};

        object u, v, w, x, y, z;
        u = "string u";
        w = "string w";
        v = "string v";
        x = "string x";
        y = "string y";
        z = "string z";

        i.Add("i1",u);
        h.Add("h2", arrayOfObjects);
        h.Add("h1", y);
        d.Add("d2", h);
        d.Add("d1", x);
        c.Add("c1", w);
        b.Add("b1", c);
        b.Add("b2", v);
        b.Add("b3", d);
        a.Add("a1", b);
        a.Add("a2", z);

        treeView1.Nodes.AddRange(RecurseTree(a));

This is the result:

TreeView