2009-12-10 3 views
5

Я пишу приложение GUI, где мне нужно включить редактирование свойств произвольных объектов (их типы известны только во время выполнения).PropertyGrid и динамические типы объектов

Я решил использовать элемент управления PropertyGrid для включения этой функции. Я создал следующий класс:

[TypeConverter(typeof(ExpandableObjectConverter))] 
[DefaultPropertyAttribute("Value")] 
public class Wrapper 
{ 
    public Wrapper(object val) 
    { 
     m_Value = val; 
    } 

    private object m_Value; 

    [NotifyParentPropertyAttribute(true)] 
    [TypeConverter(typeof(ExpandableObjectConverter))] 
    public object Value 
    { 
     get { return m_Value; } 
     set { m_Value = value; } 
    } 
} 

Когда я получить экземпляр объекта мне нужно редактировать, создать обертку для него и установить его в качестве выбранного объекта:

Wrapper wrap = new Wrapper(obj); 
propertyGrid.SelectedObject = wrap; 

Но я мы сталкиваемся с следующей проблемой: работа выше, как и ожидалось, только тогда, когда тип obj - это особый тип (то есть класс, который я определил сам или встроенный сложный тип), но не тогда, когда obj является примитивным.

Например, если я определяю:

[TypeConverter(typeof(ExpandableObjectConverter))] 
public class SomeClass 
{ 
    public SomeClass() 
    { 
     a = 1; 
     b = 2; 
    } 

    public SomeClass(int a, int b) 
    { 
     this.a = a; 
     this.b = b; 
    } 

    private int a; 

    [NotifyParentPropertyAttribute(true)] 
    public int A 
    { 
     get { return a; } 
     set { a = value; } 
    } 

    private int b; 

    [NotifyParentPropertyAttribute(true)] 
    public int B 
    { 
     get { return b; } 
     set { b = value; } 
    } 
} 

И сделать:

Тогда все работает набухать. С другой стороны, когда я выполняю следующее:

int num = 1; 
Wrapper wrap = new Wrapper(num); 
propertyGrid.SelectedObject = wrap; 

Тогда я могу увидеть значение «1» в сетке (и это не оттенками серого), но я не могу изменить значение. Я заметил, что если я изменил тип свойства Wrapper на «значение» на int и удалил атрибут TypeConverter, он будет работать. Я получаю такое же поведение для других примитивных типов и строк.

В чем проблема?

Заранее благодарен!

ответ

5

Если вы установите для ExpandableObjectConverter значение Value, оно не будет редактироваться, и это нормально, потому что CanConvertFrom вернет false. Если вы удалите конвертер типов, PropertyGrid будет использовать общий TypeConverter, и вы снова будете в одном и том же случае. Таким образом, обходной путь заключается в подключении более интеллектуального TypeConverter, который будет действовать как оболочка для правильного TypeConverter. Вот грязный один (у меня было не так много времени, вы будете завершить его по мере необходимости, так как я просто реализовал ConvertFrom часть):

public class MySmartExpandableObjectConverter : ExpandableObjectConverter 
{ 
    TypeConverter actualConverter = null; 

    private void InitConverter(ITypeDescriptorContext context) 
    { 
     if (actualConverter == null) 
     { 
      TypeConverter parentConverter = TypeDescriptor.GetConverter(context.Instance); 
      PropertyDescriptorCollection coll = parentConverter.GetProperties(context.Instance); 
      PropertyDescriptor pd = coll[context.PropertyDescriptor.Name]; 

      if (pd.PropertyType == typeof(object)) 
       actualConverter = TypeDescriptor.GetConverter(pd.GetValue(context.Instance)); 
      else 
       actualConverter = this; 
     } 
    } 

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     InitConverter(context); 

     return actualConverter.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     InitConverter(context); // I guess it is not needed here 

     return actualConverter.ConvertFrom(context, culture, value); 
    } 
} 

Позвольте мне знать, если вам нужно что-то точно настроить.

Николя

+0

Спасибо большое, что сделал трюк! :) – Marina

+0

Почему эта строка 'parentConverter.GetProperties (context.Instance);' return null? –

0

Извлеките «TypeConverter» из свойства «Значение», свойствоgrid будет считывать «TypConverter» из typeo значения, которое находится в свойстве.

+1

Я попробовал это, когда я делаю это сетка свойства отображает значение свойства правильно, но серое и редактирование отключено (он делает это даже тогда, когда OBJ не примитивный) – Marina

+0

К сожалению, MS PropertyGrid - это не тот умный hwne, который вы не установили в свой Value. Для вашего int он не вернет Int32Converter, а TypeConverter. Я знаю это, потому что мне пришлось обрабатывать этот случай в SPG. Отвечайте на мой ответ об обходном пути. –

+0

Хм, ты прав. До сих пор я жил в убеждении, что сетка свойств настолько умна. Спасибо – TcKs

 Смежные вопросы

  • Нет связанных вопросов^_^