无法在PropertyGrid中显示具有接口属性的类

时间:2011-12-16 10:16:02

标签: c# winforms .net-4.0 propertygrid

目前我正在尝试通过PropertyGrid配置我的一些类。现在,如果类提供属性作为接口,我有一些关于显示值(网格中的右侧)的问题。我想,因为网格使用反射它将采用真实类型并使用它的正常方式来显示网格中的值。对于演示,只需使用下面的类层次结构并使用PropertyGrid创建一个简单的表单,并通过调用

将对象放入其中
propertyGrid1.SelectedObject = new MyContainerClass();

以下是课程:

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;
    }
}

正如您所看到的,容器在所有三个属性中使用相同的对象,但在网格中,您将在类属性和对象属性上看到ToString()文本,但在接口属性上没有任何内容。 TypeConverter也仅用于使用确切类型的属性。

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

有没有办法让PropertyGrid显示接口属性后面的类的ToString()结果?

1 个答案:

答案 0 :(得分:1)

最后我在大多数情况下解决了这个问题:

出现问题,导致其PropertyDescriptor属性中的Converter返回通常是正确的转换器或至少基类TypeConverter,它至少会调用ToString()进行可视化。如果属性被定义为接口,则属性网格将获得ReferenceConverter,但是通过查看备注部分

  

ReferenceConverter通常在选址组件或设计环境的上下文中使用。如果没有组件站点或可用的ITypeDescriptorContext,则此转换器几乎没用。

我们似乎对此有一点用处。幸运的是,我已经在使用自己的PropertyDescriptor,所以我所要做的就是覆盖描述符的Converter属性并更改为以下内容:

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;
    }
}

需要显式检查ReferenceConverter,因为用户可能通过属性上的属性定义了自己的TypeEditor,这将由基础实现自动遵守。如果某人明确地通过该属性说出他喜欢ReferenceConverter,那只会导致问题,但我不认为必须处理这种情况(但可以通过检查PropertyDescriptor的属性)。