PropertyGrid中和对象的动态类型 [英] PropertyGrid and Dynamic Types of Objects

查看:397
本文介绍了PropertyGrid中和对象的动态类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a GUI application where I need to enable editing properties of arbitrary objects (their types are only known at run-time).

我已经决定使用PropertyGrid控件启用此功能。
我创建了以下类:

I've decided to use the PropertyGrid control to enable this functionality. I created the following 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; }
        }
}

当我得到一个对象,我需要的一个实例编辑,我为它创建一个包装并将其设置为选定对象:

When I get an instance of an object I need to edit, I create a Wrapper for it and set it as the selected object:

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



不过,我碰到以下问题 - 上述工程预期obj的类型,只有当一些自定义类型(即我自己定义的类,或者一个内置的复杂类型),而不是在obj是一个原始的。

But I've run into the following problem - the above works as expected only when the type of obj is some custom type (i.e a class that I defined by myself, or a built in complex type) but not when obj is a primitive.

例如,如果我定义

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



然后一切正常膨胀。在另一方面,当我执行以下操作:

Then everything works swell. On the other hand, when I perform the following:

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



然后,我可以看到价值在网格中1(而且它不是grayscaled),但我'T编辑值。我注意到,如果我改变包装的值属性的类型为int和删除的TypeConverter属性,它的工作原理。
我得到了其他基本类型和字符串相同的行为。

Then I can see the value "1" in the grid (and it's not grayscaled) but I can't edit the value. I noticed that if I change Wrapper's "Value" property's type to int and remove the TypeConverter attribute, it works. I get the same behavior for other primitive types and strings.

这是什么问题?

提前感谢!

推荐答案

如果您设置ExpandableObjectConverter你Value属性,它不会被编辑,这是正常的,因为CanConvertFrom将返回false。如果删除类型转换器,PropertyGrid中会使用通用的TypeConverter,你又在同一案件。因此,解决方法是将附加一个聪明的类型转换器,将作为一个包装到正确的TypeConverter。下面是一荤一(我没有太多的时间,您将完成它作为必要的,因为我刚刚实施的ConvertFrom部分):

If you set ExpandableObjectConverter to your Value property, it won't be editable and this is normal because CanConvertFrom will return false. IF you remove the type converter, the PropertyGrid will use the generic TypeConverter and you are again in the same case. So the workaround is to attach a smarter TypeConverter that will act as a wrapper to the correct TypeConverter. Here is a dirty one (I had not much time, you will complete it as needed since I just implemented the ConvertFrom part):

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

让我知道如果你需要微调一些东西。

Let me know if you need to finetune something.

萨科

这篇关于PropertyGrid中和对象的动态类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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