jeudi 10 mars 2016

How to view properties of an object or class in WPF using TreeView

I have been looking for ways to best achieve this task and settled on this.

http://ift.tt/1QPuUD7

It does seem to give me what i was hoping for but when i try to obtain the object properties of a thread, i end up getting a stackoverflow exception. So it seems that the objectNode class is instantiating itself in a recursive manner too many times and then something happens which causes a stackoverflow? I am not sure how to go about resolving this and making it work even for a class with many properties (like threads) and any help will be greatly appreciated.

The objectNode class is shown below

using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Reflection;

namespace Server.Host
{
    public class ObjectNode 
    {
        #region Private Properties
        private string _name;
        private object _value;
        private Type _type;
        #endregion

        #region Constructor
        public ObjectNode(object value) 
        {
            ParseObjectTree("root", value, value.GetType());
        }

        public ObjectNode(string name, object value)
        {
            ParseObjectTree(name, value, value.GetType());
        }

        public ObjectNode(object value, Type t)
        {
            ParseObjectTree("root", value, t);
        }

        public ObjectNode(string name, object value, Type t)
        {
            ParseObjectTree(name, value, t);
        }
        #endregion

        #region Public Properties
        public string Name
        {
            get { return _name; }
        }

        public object Value
        {
            get { return _value; }
        }

        public Type Type
        {
            get { return _type; }
        }

        public ObservableCollection<ObjectNode> Children { get; set; }
        #endregion

        #region Private Methods
        private void ParseObjectTree(string name, object value, Type type)
        {
            Children = new ObservableCollection<ObjectNode>();

            _type = type;
            _name = name;

            if (value != null)
            {
                if (value is string && type != typeof(object))
                {
                    if (value != null)
                    {
                        _value = "\"" + value + "\"";
                    }
                }
                else if (value is double || value is bool || value is int || value is float || value is long || value is decimal)
                {
                    _value = value;
                }
                else
                {
                    _value = "{" + value.ToString() + "}";
                }
            }

            PropertyInfo[] props = type.GetProperties();

            if (props.Length == 0 && type.IsClass && value is IEnumerable && !(value is string))
            {
                IEnumerable arr = value as IEnumerable;

                if (arr != null)
                {
                    int i = 0;
                    foreach (object element in arr)
                    {
                        Children.Add(new ObjectNode("[" + i + "]", element, element.GetType()));
                        i++;
                    }
                }
            }

            foreach (PropertyInfo p in props)
            {
                if (p.PropertyType.IsPublic)
                {
                    if (p.PropertyType.IsClass || p.PropertyType.IsArray || p.PropertyType.IsInterface)
                    {
                        if (p.PropertyType.IsArray)
                        {
                            try
                            {
                                object v = p.GetValue(value, null);
                                IEnumerable arr = v as IEnumerable;

                                ObjectNode arrayNode = new ObjectNode(p.Name, arr.ToString(), typeof(object));

                                if (arr != null)
                                {
                                    int i = 0, k = 0;
                                    ObjectNode arrayNode2;

                                    foreach (object element in arr)
                                    {
                                        //Handle 2D arrays
                                        if (element is IEnumerable && !(element is string))
                                        {
                                            arrayNode2 = new ObjectNode("[" + i + "]", element.ToString(), typeof(object));

                                            IEnumerable arr2 = element as IEnumerable;
                                            k = 0;

                                            foreach (object e in arr2)
                                            {
                                                arrayNode2.Children.Add(new ObjectNode("[" + k + "]", e, e.GetType()));
                                                k++;
                                            }

                                            arrayNode.Children.Add(arrayNode2);
                                        }
                                        else
                                        {
                                            arrayNode.Children.Add(new ObjectNode("[" + i + "]", element, element.GetType()));
                                        }
                                        i++;
                                    }

                                }

                                Children.Add(arrayNode);
                            }
                            catch { }
                        }
                        else
                        {
                            object v = p.GetValue(value, null);

                            if (v != null)
                            {
                                Children.Add(new ObjectNode(p.Name, v, p.PropertyType));
                            }
                        }
                    }
                    else if (p.PropertyType.IsValueType && !(value is string))
                    {
                        try
                        {
                            object v = p.GetValue(value, null);

                            if (v != null)
                            {
                                Children.Add(new ObjectNode(p.Name, v, p.PropertyType));
                            }
                        }
                        catch { }
                    }
                }
            }
        }

        #endregion
    }
}

So from this, the TreeView can be added in the WPF simply as

<TreeView Name="ResultTreeView" BorderThickness="0">
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type local:ObjectNode}" 
                                              ItemsSource="{Binding Path=Children}">
                        <TreeViewItem>
                            <TreeViewItem.Header>
                                <StackPanel Orientation="Horizontal" Margin="-10,0,0,0">
                                    <TextBlock Text="{Binding Path=Name}"/>
                                    <TextBlock Text=" : "/>
                                    <TextBlock Text="{Binding Path=Value}"/>
                                </StackPanel>
                            </TreeViewItem.Header>
                        </TreeViewItem>
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>

Then in my code, I simply write

private Foo foo = new Foo();
ObservableCollection<ObjectNode> nodes = new ObservableCollection<ObjectNode>();
nodes.Add(new ObjectNode("result", foo));
ResultTreeView.ItemsSource = nodes;

Where Foo can be any class. For most things it is working fine. But if i have a thread in the class, it will throw an exception. For example just a simple

public class Foo
{
    public Foo()
    {
        Bar = new Thread(Baz);
    }

    public Thread Bar { get; set; }

    private static void Baz()
    {
    }
}

The error that is thrown is "An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll"

Once again, any advice is greatly welcomed.





Aucun commentaire:

Enregistrer un commentaire