PropertyGrid和动态对象类型

我正在编写一个GUI应用程序,我需要启用任意对象的编辑属性(它们的类型仅在运行时才知道)。

我决定使用PropertyGrid控件来启用此function。 我创建了以下类:

[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的类型是某种自定义类型(即我自己定义的类,或者内置的复杂类型)时才能按预期工作,但是当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的“Value”属性的类型更改为int并删除TypeConverter属性,它就可以工作。 我得到了其他原始类型和字符串相同的行为。

问题是什么?

提前致谢!

如果将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); } } 

如果您需要微调某些东西,请告诉我。

萨科

从属性“Value”中删除“TypeConverter”,propertygrid将从属性中的typeo中读取“TypConverter”。