2

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!

5
  • 1
    Possible duplicate of How to put an extended WinForms Control on ToolBox Commented Jun 20, 2016 at 21:10
  • 1
    @Zack That doesn't look like a duplicate. Commented Jun 20, 2016 at 21:13
  • @Zack, not even close to what I'm trying to achieve here... Commented Jun 20, 2016 at 21:13
  • msdn.microsoft.com/en-us/library/ms171840.aspx Commented Jun 20, 2016 at 21:47
  • @RezaAghaei I agree. I thought it was a good answer, so I've neutralised the downvote Commented Jun 21, 2016 at 18:32

1 Answer 1

2

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";
    }
}
Sign up to request clarification or add additional context in comments.

17 Comments

While the answer is completely correct a downvote is really strange!
with this answer, say for example someone designs their own brush that extends CustomBrush, can this example be used to dynamically find implementations of CustomBrush, say using reflection, and add them to the list? Would that work?
The solution is relied on standardValues array and instances of CustomBrush which it contains. So the answer is Yes. In an implementation I used ITypeDiscoveryService to find desired types and added them to the standard values collection.
Okay, so I've implemented this, however there is a bit of a snag...the dropdown list is definitely along the right lines, but say for example each CustomBrush implementation has properties that I also want to manipulate via the designer (i.e. SolidCustomBrush has a Color property, and I want to set it's Color)...can this be achieved also?
@deveton About UiTypeEditor, it controls the editing part (like showing a modal dialog). Serialization is responsibility of the serialization-related attributes and the type converter.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.