Propertygrid with multiple nested classes

7.1k Views Asked by At

I've been playing around with PropertyGrids, linking them to classes and am trying to figure out how (if possible) I can display a class, with sub classes inside the PropertyGrid in a flat structure (as if they were all in one class)

I have a couple of classes, Foo and Bar as per below:

[Serializable()]
public class Foo
{
    private string m_Code;
    private Bar m_Bar = new Bar();

    [DisplayName("Code")]
    [Description("The Code of Foo")]
    public string Code
    {
        get { return m_Code; }
        set { m_Code = value; }
    }

    public Bar Bar
    {
        get { return m_Bar; }
        set { m_Bar = value; }
    }
}

and

[TypeConverter(typeof(ExpandableObjectConverter))]
[Serializable()]
public class Bar
{
    private string m_Name;

    [DisplayName("Name")]
    [Description("The Name of Bar")]
    public string Name
    {
        get { return m_Name; }
        set { m_Name = value; }
    }
}

What I am trying to understand / figure out is if I can modify the way that the data is then displayed in the PropertyGrid.

Specifically I would like to display both Foo.Code and Bar.Name in a flat / organised structure, the same way as if they were both in the same class.

If I use don't use a TypeConverter, or attempt to use [TypeConverter(typeof(Bar))] then I see my Bar class in the PropertyGrid, but just a single line, and can't edit the Name property.

If I use [TypeConverter(typeof(ExpandableObjectConverter))] as above, then I can see an expand arrow for Bar, and underneath that the property for Name... all seems good.

However, I both have to expand the group, and it displays the class name to the right hand side. Obviously I can call PropertyGrid.ExpandAllGridItems(); as needed, but it is also ugly.

If I use [Category("Bar")], then it is included, and organised in the flat structure as desired, but still with the above problems (expand level and class name)

Am I missing something obvious here? Or is it a case that I need to implement some kind of custom type converter? And if so, how to go about doing that?

Edit:

To clarify further, when I use nested class, it is displayed like below, so shows the class name on the right, and expand arrow.

enter image description here

I would like to have the nested classes like as shown below / as if Foo was just one class with Code and Name.

enter image description here

Edit2:

Trying to implement a Type convertor, and that seems to be displaying ok, but now I can't edit the value at all (i.e Bar.Name )

[TypeConverter(typeof(BarConverter))]
[Serializable()]
public class Bar
{
    private string m_Name;

    [DisplayName("Name")]
    [Description("The Name of Bar")]
    public string Name
    {
        get { return m_Name; }
        set { m_Name = value; }
    }
}

public class BarConverter : TypeConverter
{
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        Bar _Bar = (Bar)value;
        return _Bar.Name;
    }

}

Edit 3:

Type converter seems to work for getting the values, but now cannot edit the Bar.Name values, it is just greyed out:

enter image description here

Current TypeConverter

public class BarConverter : TypeConverter
{
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        Bar _Bar = (Bar)value;
        return _Bar.Name;
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        return base.ConvertFrom(context, culture, value);
    }
}

Edit #4

I think this is going in the too hard basket. Too much time going round in circles :(

2

There are 2 best solutions below

0
On

I've solved a similar problem by just overriding the class's ToString() method. Solution found here.

[Serializable()]
public class Bar
{
    private string m_Name;

    [DisplayName("Name")]
    [Description("The Name of Bar")]
    public string Name
    {
        get { return m_Name; }
    }
    public override string ToString()
    {
        return "Name you want to display";
    }
}
0
On

I think you should override ExpandableObjectConverter instead of TypeConverter.

public class BarConverter : ExpandableObjectConverter
    {
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
             Bar _Bar = (Bar) value;
             return _Bar.Name;
        }
    }