不同派生类型的 WinForms 设计器属性

WinForms designer properties of different derived types

假设我有一个特定类型,我想提供给 Windows 表单设计器...

public class Style
{
    public CustomBrush Brush { get; set; }
}

并且CustomBrush是这样实现的...

public abstract CustomBrush
{
    ...
}

public SolidCustomBrush : CustomBrush
{
    ...
}

public GradientCustomBrush : CustomBrush
{
    ...
}

有没有一种方法可以在设计时从 CustomBrush 派生的任何类型中进行选择,实例化所选类型的实例,然后通过设计器对其进行修改?

到目前为止,我唯一能做到这一点的方法是使用 enum

enum BrushType
{
    Solid,
    Gradient
}

enum 发生变化时,Brush 属性 的底层类型也会发生变化,但我不喜欢这种方法...它很脏!

作为一个选项,您可以创建自定义 TypeConverter,它提供要在 PropertyGrid 中显示的标准值列表。

A type converter can provide a list of values for a type in a Properties window control. When a type converter provides a set of standard values for a type, the value entry field for a property of the associated type in a Properties window control displays a down arrow that displays a list of values to set the value of the property to when clicked.

由于您还希望能够编辑 属性 网格中 CustomBrush 的子属性,因此您应该从 ExpandableObjectConverter 派生。

结果

实施

创建一个 CustomBrushConverter class 并派生自 ExpandableObjectConverter。然后覆盖这些方法:

using System;
using System.ComponentModel;
using System.Linq; 
class CustomBrushConverter : ExpandableObjectConverter
{
    CustomBrush[] standardValues = new CustomBrush[] { new SolidCustomBrush(), new GradientCustomBrush() };
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        var result = standardValues.Where(x => x.ToString() == value).FirstOrDefault();
        if (result != null)
            return result;
        return base.ConvertFrom(context, culture, value);
    }
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(standardValues);
    }
}

然后用 TypeConverterAttribute 修饰 Brush 属性:

public class Style /*: Component */
{
    [TypeConverter(typeof(CustomBrushConverter))]
    public CustomBrush Brush { get; set; }
}

您可以覆盖 CustomBrush class 的 ToString 方法,以提供更友好的名称以显示在 PropertyGrid 的下拉列表中。例如:

public class GradientCustomBrush : CustomBrush
{
    public Color Color1 { get; set; }
    public Color Color2 { get; set; }
    public override string ToString()
    {
        return "Gradient";
    }
}