Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
278 views
in Technique[技术] by (71.8m points)

c# - WinForms designer properties of different derived types

Say I have a particular type that I want to make available to the Windows Forms designer...

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

And CustomBrush is implemented like so...

public abstract CustomBrush
{
    ...
}

public SolidCustomBrush : CustomBrush
{
    ...
}

public GradientCustomBrush : CustomBrush
{
    ...
}

Is there a way at design time that I can choose from any of the types derived from CustomBrush, instantiate an instance of the selected type, and modify it via the designer?

So far the only way I've though of to be able to do this is using an enum

enum BrushType
{
    Solid,
    Gradient
}

When the enum changes, so does type underlying the Brush property, but I don't like this approach...it's dirty!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As an option you can create a custom TypeConverter that provides a list of standard values to show in 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.

Since you want to be able to edit also sub properties of the CustomBrush in property grid, you should derive from ExpandableObjectConverter.

Result

enter image description here

enter image description here

enter image description here

Implementation

Create a CustomBrushConverter class and derive from ExpandableObjectConverter. Then override these methods:

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

Then decorate the Brush property with TypeConverterAttribute this way:

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

You can override ToString method of your CustomBrush classes to provide more friendly names to show in dropdown list in PropertyGrid. For example:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...