无法在PropertyGrid中显示具有接口属性的类 [英] Can't show class with interface properties in PropertyGrid

查看:96
本文介绍了无法在PropertyGrid中显示具有接口属性的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在尝试通过PropertyGrid配置一些类。现在,如果类提供该属性作为接口,则我在显示值(网格内的右侧)时遇到一些问题。我认为,由于网格使用反射,因此将采用实型,并使用其正常方式在网格内显示值。为了进行演示,只需采用下面的类层次结构,并创建一个带有PropertyGrid的简单表单,然后通过调用将对象放入其中

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();

以下是这些类别:

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

您可以看到容器在其中使用了相同的对象所有这三个属性,但是在网格中,您将在class属性和object属性上看到 ToString()文本,而在interface属性上则看不到任何内容。此外,TypeConverter仅用于使用确切类型的属性。

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.

显示MyContainer的PropertyGrid http://image-upload.de/image/O2CC5e/9558e4e179.png

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

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

推荐答案

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

Finally i solved this problem for the most cases:

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

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


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

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.

我们似乎真的没有多大用处。幸运的是,我已经在使用自己的 PropertyDescriptor ,所以我要做的就是重写描述符的Converter属性并更改为以下内容:

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

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

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).

这篇关于无法在PropertyGrid中显示具有接口属性的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆