类型转换器用于类型对象属性

3
我需要在属性网格中正确显示一个对象。 我的类看起来像这样:
public class PropertyItem
{
    public PropertyDescription PropertyDescription { get; set; }

    [Description("the value"), Browsable(true)]
    public object Value { get; set; }

    public PropertyItem(PropertyDescription propertyDescription, object value)
    {
        PropertyDescription = propertyDescription;
        Value = value;
    }

    public override string ToString()
    {
        return this.PropertyDescription.Name + ": " + PropertyDescription.Type + ": " + Value;
    }
}

Value 是一个 object 类型,不能改变。

PropertyDescription 的类型与 Value 相同,可以是任何类型(如 stringintbool 等)。

当我设置 PropertyGridSelectedObject 时,Value 总是被禁用。

我该如何编写一个 TypeConverter 来将 object 类型的 Value 转换为 PropertyDescription 中的 Type


可能是如何查找和调用特定类型的.Net TypeConverter?的重复问题。 - Massimiliano Kraus
请检查这个链接,看看它是否能帮到你。 - Massimiliano Kraus
显示不是主要的问题。但是,无论如何,当输入值时,必须确定其类型。"0"的类型是什么?这种方法是错误的。 - Hans Passant
嗨,汉斯,我假设我的列表将包含正确的值和正确的类型...你说得对,但我暂时没有考虑到这一点...谢谢你的提示。 - lebhero
1个回答

5

为属性定义自定义类型转换器:

[TypeConverter(typeof(PropertyValueConverter))]
public object Value { get; set; }

并像这样实现:

public class PropertyValueConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        var propItem = context.Instance as PropertyItem;
        return propItem != null && TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).CanConvertFrom(context, sourceType)
            || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        var propItem = context.Instance as PropertyItem;
        if (propItem != null)
            return TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).ConvertFrom(context, culture, value);
        else
            return base.ConvertFrom(context, culture, value);
    }
}

这段测试代码对我有效:

var pi = new PropertyItem(new PropertyDescription { Type = typeof(int) }, 1);
propertyGrid1.SelectedObject = pi;

更新:

为了支持下拉列表(例如布尔类型):

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        var propItem = context.Instance as PropertyItem;
        if (propItem != null)
            return TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).GetStandardValues(context);
        else
            return base.GetStandardValues(context);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        var propItem = context.Instance as PropertyItem;
        if (propItem != null)
            return TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).GetStandardValuesSupported(context);
        else
            return base.GetStandardValuesSupported(context);
    }

为了支持自定义可打开的属性(例如Point):

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        var propItem = context.Instance as PropertyItem;
        if (propItem != null)
            return TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).GetProperties(context, value, attributes);
        else
            return base.GetProperties(context, value, attributes);
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        var propItem = context.Instance as PropertyItem;
        if (propItem != null)
            return TypeDescriptor.GetConverter(propItem.PropertyDescription.Type).GetPropertiesSupported(context);
        return base.GetPropertiesSupported(context);
    }

如果我检查一个布尔类型的值,属性网格将显示该值,但不会以只有True或False的下拉列表形式,而是一个空文本框。 - lebhero
pi = new PropertyItem(new PropertyDescription { Type = typeof(bool) }, true); 对我来说很有效:它不显示空文本框,我可以编辑值。要提供布尔常量的下拉列表,请以相同的方式覆盖 GetProperties 方法。 - György Kőszeg
你介意编辑一下你上面的回答,包括你所说的GetProperties重写吗? - lebhero
谢谢...我用点测试了一下,它可以工作...但是使用布尔类型还有一些问题,它没有显示下拉列表,但我会检查并告诉你的..再次感谢 - lebhero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接