Не удается отобразить класс со свойствами интерфейса в PropertyGrid - PullRequest
1 голос
/ 16 декабря 2011

В настоящее время я пытаюсь настроить некоторые из моих классов через 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, показывающий MyContainer http://image -upload.de / image / O2CC5e / 9558e4e179.png

Существует ли какой-либо способ, позволяющий PropertyGrid отображать результат ToString () класса за свойством интерфейса?

1 Ответ

1 голос
/ 09 января 2012

Наконец я решил эту проблему для большинства случаев:

Проблема возникает из-за того, что 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).

...