WPF DataGrid - Color Cells on Graded Color Scale

c#, colors, converters, wpf

Solution

I've created a ValueToBrushConverter. You use it like this:

Background="{Binding Path=YourDoubleValue,
                     Converter={StaticResource ValueToBrushConverter},
                     ConverterParameter='YourMinDouble|YourMaxDouble'}"

This will create a gradient color scale from green (`YourMinDouble`) to red (`YourMaxDouble`) and pick the related color for `YourDoubleValue`. `YourMinDouble` can be negativ but has to be lesser then `YourMaxDouble`. If `YourDoubleValue` is not in range it returns `Brushes.Transparent`. Customize it for your needs!

ConverterClass

[ValueConversion(typeof(double), typeof(Brush))]
class ValueToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double number = (double)value;
        double min = 0;
        double max = 100;

        // Get the value limits from parameter
        try
        {
            string[] limits = (parameter as string).Split(new char[] { '|' });
            min = double.Parse(limits[0], CultureInfo.InvariantCulture);
            max = double.Parse(limits[1], CultureInfo.InvariantCulture);
        }
        catch (Exception)
        {
            throw new ArgumentException("Parameter not valid. Enter in format: 'MinDouble|MaxDouble'");
        }

        if (max <= min)
        {
            throw new ArgumentException("Parameter not valid. MaxDouble has to be greater then MinDouble.");
        }

        if (number >= min && number <= max)
        {
            // Calculate color channels
            double range = (max - min) / 2;
            number -= max - range;
            double factor = 255 / range;
            double red = number < 0 ? number * factor : 255;
            double green = number > 0 ? (range - number) * factor : 255;

            // Create and return brush
            Color color = Color.FromRgb((byte)red, (byte)green, 0);
            SolidColorBrush brush = new SolidColorBrush(color);
            return brush;
        }

        // Fallback brush
        return Brushes.Transparent;
    }

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

Problem

I'm trying to figure out if there is a way to color individual cells on a color scale. In particular, I am hoping to get something like the Bonus column in the following: Currently, I've setup my datagrid's columns background property to bind to the following converter: ``` public class NameToBrushConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double? input = value as double?; if(input<-5) { return Brushes.MediumVioletRed; } if(-5<=input && input<-0.5) { return Brushes.IndianRed; } if (.5 <= input && input < 5) { return Brushes.LightGreen; } if (5 <= input) { return Brushes.LawnGreen; } return DependencyProperty.UnsetValue; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotSupportedException(); } } } ``` Is there a way, without hard coding the values, to get a color scale? Thanks - kcross EDIT: I'm also trying to create a better Red-Green color scale (ie for negative to positive numbers), in terms of one that is a little less hard on the eyes.... if anyone has any suggestions on that as well that's also appreciated!

Original source