53

I want to convert a System.Windows.Media.Color value to a System.Windows.Media.Brush. The color value is databound to a Rectangle object's Fill property. The Fill property takes a Brush object, so I need an IValueConverter object to perform the conversion.

Is there a built-in converter in WPF or do I need to create my own? How do I go about creating my own if it becomes necessary?

dthrasher
  • 36,940
  • 32
  • 104
  • 137
  • Possible duplicate: http://stackoverflow.com/questions/372693/convert-string-to-brushes-brush-name-in-c – Jakob Christensen Jul 22 '10 at 14:11
  • 3
    I don't think it's a duplicate. I want to convert from a Color object, not a string value like "Red." And I'd like to implement it as a XAML converter, vs. performing the conversion in C# code behind. – dthrasher Jul 22 '10 at 14:28

7 Answers7

141

I know I am really late to the party, but you don't need a converter for this.

You could do

<Rectangle>
    <Rectangle.Fill>
        <SolidColorBrush Color="{Binding YourColorProperty}" />
    </Rectangle.Fill>
</Rectangle>
Jens
  • 23,903
  • 6
  • 72
  • 114
  • 2
    This solution is much better than the accepted answer. Thanks! – Antoine Aubry Nov 02 '12 at 17:24
  • 6
    Though I like this solution, it does indeed result in annoying warnings as described here: http://stackoverflow.com/questions/7926204/cannot-find-governing-frameworkelement-warning-when-binding-inside-datatemp – l33t May 22 '14 at 09:49
  • 1
    If you're confused about what `YourColorProperty` is like I was, it's most likely a property that is viewable from the current XAML scope in your C# code-behind. – Nathaniel Ruiz Jan 16 '19 at 20:00
68

It seems that you have to create your own converter. Here a simple example to start:

public class ColorToSolidColorBrushValueConverter : IValueConverter {

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
        if (null == value) {
            return null;
        }
        // For a more sophisticated converter, check also the targetType and react accordingly..
        if (value is Color) {
            Color color = (Color)value;
            return new SolidColorBrush(color);
        }
        // You can support here more source types if you wish
        // For the example I throw an exception

        Type type = value.GetType();
        throw new InvalidOperationException("Unsupported type ["+type.Name+"]");            
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
        // If necessary, here you can convert back. Check if which brush it is (if its one),
        // get its Color-value and return it.

        throw new NotImplementedException();
    }
}

To use it, declare it in the resource-section.

<local:ColorToSolidColorBrushValueConverter  x:Key="ColorToSolidColorBrush_ValueConverter"/>

And the use it in the binding as a static resource:

Fill="{Binding Path=xyz,Converter={StaticResource ColorToSolidColorBrush_ValueConverter}}"

I have not tested it. Make a comment if its not working.

Ivar
  • 4,655
  • 12
  • 45
  • 50
HCL
  • 34,231
  • 24
  • 150
  • 202
  • Thanks a bunch @Chris Valentine. Even though Jens' answer has great elegance, in my case I was not able to use it and I had to use the Converter. Or perhaps I could not see how to implement SolidColorBrush in my case. – philologon May 24 '14 at 18:14
12

A Converter is not needed here. You can define a Brush in XAML and use it. It would be better to define the Brush as a Resource so it can be used other places required.

XAML is as below:

<Window.Resources>
    <SolidColorBrush Color="{Binding ColorProperty}" x:Key="ColorBrush" />
</Window.Resources>
<Rectangle Width="200" Height="200" Fill="{StaticResource ColorBrush}" />
Kylo Ren
  • 7,647
  • 4
  • 36
  • 57
7

I wanted to do this HCL's way rather than Jens' way because I have a lot of things bound to the Color, so there's less duplication and boiler-plate .Fill nodes.

However when trying to write it, ReSharper pointed me to the WPF Toolkit's implementation of the ColorToSolidColorBrushConverter. You need to include the following namespace declaration in the main Window/UserControl node:

xmlns:Toolkit="clr-namespace:Microsoft.Windows.Controls.Core.Converters;assembly=WPFToolkit.Extended"

Then a static resource in the Window/UserControl resources:

<Toolkit:ColorToSolidColorBrushConverter x:Key="colorToSolidColorBrushConverter" />

Then you can do it like HCL's answer:

<Rectangle Fill="{Binding Color, Converter={StaticResource colorToSolidColorBrushConverter}}" />
Jackson Pope
  • 13,897
  • 6
  • 52
  • 80
3

With some more enhancment to HCL answer, I tested it - it works.

public class ColorToSolidColorBrushValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        if (value is Color)
            return new SolidColorBrush((Color)value);

        throw new InvalidOperationException("Unsupported type [" + value.GetType().Name + "], ColorToSolidColorBrushValueConverter.Convert()");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        if (value is SolidColorBrush)
            return ((SolidColorBrush)value).Color;

        throw new InvalidOperationException("Unsupported type [" + value.GetType().Name + "], ColorToSolidColorBrushValueConverter.ConvertBack()");
    }

}
G.Y
  • 5,341
  • 2
  • 30
  • 51
1

Converter:

[ValueConversion(typeof(SolidColorBrush), typeof(Color))]
public class SolidBrushToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is SolidColorBrush)) return null;
        var result = (SolidColorBrush)value;
        return result.Color;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

//...
<converters:SolidBrushToColorConverter x:Key="SolidToColorConverter" />
//...
<Color>
    <Binding Source="{StaticResource YourSolidColorBrush}"
             Converter="{StaticResource SolidToColorConverter}">
    </Binding>
</Color>
//...
Stacked
  • 5,676
  • 5
  • 52
  • 69
1

In addition to HCLs answer: If you don't want to care if System.Windows.Media.Color is used or System.Drawing.Color you can use this converter, which accepts both:

public class ColorToSolidColorBrushValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        switch (value)
        {
            case null:
                return null;
            case System.Windows.Media.Color color:
                return new SolidColorBrush(color);
            case System.Drawing.Color sdColor:
                return new SolidColorBrush(System.Windows.Media.Color.FromArgb(sdColor.A, sdColor.R, sdColor.G, sdColor.B));
        }

        Type type = value.GetType();
        throw new InvalidOperationException("Unsupported type [" + type.Name + "]");
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
} 
Norman
  • 2,789
  • 3
  • 19
  • 37