Can't show class with interface properties in PropertyGrid

别来无恙 提交于 2020-01-05 07:05:14

问题


Currently i'm trying to configure some of my classes through the PropertyGrid. Now i have some problems about showing the value (the right side within the grid) if the class provides the property as an interface. I thought, cause the grid uses reflection it would take the real type and uses it's normal ways on showing the value within the grid. For a demonstration simply take the class hierarchy below and create a simple form with a PropertyGrid and put the object into it by calling

propertyGrid1.SelectedObject = new MyContainerClass();

Here are the classes:

public class MyContainerClass
{
    // Simple properties that should be shown in the PropertyGrid
    public MyInterface MyInterface { get; set; }
    public MyClass MyClass { get; set; }
    public object AsObject { get; set; }

    public MyContainerClass()
    {
        // Create one instance of MyClass
        var myClass = new MyClass();

        // Put the instance into both properties
        // (cause MyClass implements MyInterface)
        MyClass = myClass;
        MyInterface = myClass;

        // and show it if it is declared as "object"
        AsObject = myClass;
    }
}

// Some kind of interface i'd like to show in the PropertyGrid.
public interface MyInterface
{
    string Name { get; set; }
}

// A class that also implements the interface
// and uses some kind of TypeConverter
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyClass : MyInterface
{
    // Create an instance and put something meaningful into the property.
    public MyClass()
    {
        Name = "MyName";
    }

    public string Name { get; set; }

    // Override ToString() to get something shown
    // as value in the PropertyGrid.
    public override string ToString()
    {
        return "Overridden ToString(): " + Name;
    }
}

As you can see the container uses the same object in all three properties, but within the grid you'll see the ToString() text on the class property and on the object property, but nothing on the interface property. Also the TypeConverter is only used on the property that uses the exact type.

PropertyGrid showing MyContainer http://image-upload.de/image/O2CC5e/9558e4e179.png

Exists there any way to let the PropertyGrid showing the ToString() result of the class behind the interface property?


回答1:


Finally i solved this problem for the most cases:

The problem occurs, cause the PropertyDescriptor returns within its Converter property normally the correct converter or at least the base class TypeConverter which will at least call ToString() for visualization. In case of a property that is defined as an interface the property grid will get a ReferenceConverter, but by looking into the remarks section

The ReferenceConverter is typically used within the context of sited components or a design environment. Without a component site or a usable ITypeDescriptorContext, this converter is of little use.

We really seem to have a little use for it. Fortunately i'm already using my own PropertyDescriptor, so all i had to do was to override the Converter property of my descriptor and change to the following:

public override TypeConverter Converter
{
    get
    {
        var converter = base.Converter;

        // If the property of the class is a interface, the default implementation
        // of PropertyDescriptor will return a ReferenceConverter, but that doesn't
        // work as expected (normally the right site will stay empty).
        // Instead we'll return a TypeConverter, that works on the concrete type
        // and returns at least the ToString() result of the given type.
        if (_OriginalPropertyDescriptor.PropertyType.IsInterface)
        {
            if (converter.GetType() == typeof(ReferenceConverter))
            {
                converter = _InterfaceConverter;
            }
        }

        return converter;
    }
}

The explicit check for the ReferenceConverter is needed, cause it could be possible that the user defined its own TypeEditor through an attribute on the property, which will be automatically respected by the base implementation. It would only lead to problems if someone would explicit say through the attribute, that he likes the ReferenceConverter, but i don't think that case has to be handled (but could be by checking the attributes of the PropertyDescriptor).



来源:https://stackoverflow.com/questions/8532719/cant-show-class-with-interface-properties-in-propertygrid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!