PropertyGrid и динамические типы объектов

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

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

[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 для него и устанавливаю его как выделенный объект:

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

Но я столкнулся с следующей проблемой: вышеупомянутое работает так, как ожидалось, только когда тип obj – это особый тип (то есть class, который я определил сам или встроенный сложный тип), но не когда 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; } } } 

И делать:

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

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

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

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

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

Заранее спасибо!

Если вы установите для ExpandableObjectConverter значение Value, оно не будет редактироваться, и это нормально, потому что CanConvertFrom вернет false. Если вы удалите конвертер типов, PropertyGrid будет использовать общий TypeConverter, и вы снова будете в одном и том же случае. Таким образом, обходной путь заключается в подключении более интеллектуального TypeConverter, который будет действовать как shell для правильного 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); } } 

Дайте мне знать, если вам нужно что-то сделать.

никола

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