Programmatically get a brush from the Brushes class?
Asked Answered
R

4

5

I have a property that allows the string name of a known colour to be sent to my control. The property only accepts proper known colour names, like "Red" or "Blue"

  private KnownColor _UseColor = KnownColor.Red;

    /// <summary>
    /// Gets or sets the name of the colour
    /// </summary>
    public string ColorName
    {
        get
        {
            return this._UseColor.ToString();
        }
        set
        {
            if (Enum.IsDefined(typeof(KnownColor), value))
                this._UseColour = (KnownColor)Enum.Parse(typeof(KnownColor), value);
        }
    }

And what I want to do is use this _UseColour enumeration to select an existing brush from the static Brushes class in .NET like this

Brush sysBrush = Brushes.FromKnownColor(this._UseColor);
e.Graphics.FillRectangle(sysBrush, 0, 0, 10, 10);

Instead of creating a new brush whenever the control is painted like this

using (SolidBrush brsh = new SolidBrush(Color.FromKnownColor(this._UseColor)))
    e.Graphics.FillRectangle(brsh, 0, 0, 10, 10);

Does anyone know if this is possible or will I have to create a new brush every time?

Brushes.FromKnownColor isn't a method in the Brushes class

Rombert answered 28/2, 2013 at 11:17 Comment(0)
P
4

Why not create the brush once and cache it for later use?

In your main class:

private KnownColor _UseColor = KnownColor.Red;

/// <summary>
/// Gets or sets the name of the colour
/// </summary>
public string ColorName
{
    get
    {
        return this._UseColor.ToString();
    }
    set
    {
        if (Enum.IsDefined(typeof(KnownColor), value))
            this._UseColour = (KnownColor)Enum.Parse(typeof(KnownColor), value);
    }
}

private Dictionary<string, Brush> _knownBrushes = new Dictionary<string, Brush>();

public Brush ColorBrush
{
    get
    {
        if (!_knownBrushes.ContainsKey(_UseColor)) {
            _knownBrushes[_UseColor] = new SolidBrush(Color.FromKnownColor(this._UseColor));
        }

        return _knownBrushes[_UseColor];
    }
}

then use it like..

e.Graphics.FillRectangle(ColorBrush, 0, 0, 10, 10);
Playoff answered 28/2, 2013 at 11:21 Comment(3)
I like that thanks :) is it generally better to cache brush objects than creating them on the fly? Wouldn't I then have to make my class disposable to dispose the _knownBrushes at the end?Rombert
You can make it dispose each brush in a destructor for your class yes.Playoff
There probably won't be a huge amount in _knownBrushes but I'd still opt for a call to TryGetValue() rather than the double-lookup in the getter.Lingua
A
2

The reflection approach

var properties = typeof (Brushes).GetProperties();
var property = properties.FirstOrDefault(p => p.Name == "Red");
var brush = property.GetValue(null, null); // Contains Brushes.Red

Your case

Field:

PropertyInfo[] _properties = typeof (Brushes).GetProperties();

Static method

static Brush GetKnownBrush(string knownColorName)
{
    var property = _properties.FirstOrDefault(p => p.Name == knownColorName);
    var brush = property.GetValue(null, null);
    return brush;
}

Usage:

var knownBrush = GetKnownBrush(ColorName);

Instance property

Brush KnownBrush
{
    get
    {
        var property = _properties.FirstOrDefault(p => p.Name == ColorName);
        var brush = property.GetValue(null, null);
        return brush;
    }
}

Usage:

var knownBrush = KnownBrush;

You can also store frequently utilized brushes in a dictionary in order to avoid reflection actions.

Annabelannabela answered 28/2, 2013 at 11:25 Comment(0)
C
1

If you want a solution that can look up the brush by a color, even if the color might not have a known name, you can create a dictionary that uses the color:

void Main()
{
    var brush = KnownBrush(Color.FromArgb(255, 0, 0));
    brush.Dump();
}

private static Dictionary<Tuple<byte, byte, byte, byte>, SolidBrush> _KnownBrushes;
public static SolidBrush KnownBrush(Color color)
{
    if (_KnownBrushes == null)
    {
        _KnownBrushes = new Dictionary<Tuple<byte, byte, byte, byte>, SolidBrush>();
        foreach (var propertyInfo in typeof(Brushes).GetProperties())
        {
            if (propertyInfo.PropertyType == typeof(Brush))
            {
                var brush = propertyInfo.GetValue(null) as SolidBrush; // not a typo
                if (brush != null)
                    _KnownBrushes[Tuple.Create(brush.Color.R, brush.Color.G, brush.Color.B, brush.Color.A)] = brush;
            }
        }
    }

    SolidBrush result;
    _KnownBrushes.TryGetValue(Tuple.Create(color.R, color.G, color.B, color.A), out result);
    return result;
}
Cobbie answered 28/2, 2013 at 11:25 Comment(0)
S
1

The other answers are complicated. Here's a one-liner to convert the string "purple" to a solid colour brush:

new SolidColorBrush((Color)ColorConverter.ConvertFromString("purple"))

Remembering using System.Windows.Media;

Sailfish answered 28/2, 2013 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.