Dynamic Gradient Background based on int value

3.5k views Asked by At

for an order overview I have a list of multiple orders with different priorities. They reach from -10 => very high priority to +20 => low priority. Based on this priority I want to return a Gradient brush Color dynamically.

For example:

  • From -10 to -0.5 it should it fade from darkred into orange
  • From -0.5 to +0.5 it should fade from orange into yellow into lime
  • From +0.5 to +10 it should fade from lime to green

I have never made this before and absolutly no clue how to solve this. Even if you don't have a complete solution for me it would be very nice to give me a hint.

Regards Johannes

5

There are 5 answers

0
Enigma On

I guess you are revering to this color: http://msdn.microsoft.com/en-us/library/system.drawing.color.aspx

Lookup this link: Is there an easy way to blend two System.Drawing.Color values?

It tells you how to blend between two colors

After this you can retrieve a brush: convert from Color to brush

0
BLoB On

You can either do some funky algorithm to tell you if priorities exist or not and add the gradient accordingly calculating the position of each gradient as required, or create a rectangluar area for each priority then add a gradient using the following method. See system.windows.media.lineargradientbrush and WPF Brushes Overview

In xaml

<Rectangle Width="200" Height="100">
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
       <GradientStop Color="Yellow" Offset="0.0" />
       <GradientStop Color="Red" Offset="0.25" />
       <GradientStop Color="Blue" Offset="0.75" />
       <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle>

then in C#

Rectangle diagonalFillRectangle = new Rectangle();
diagonalFillRectangle.Width = 200;
diagonalFillRectangle.Height = 100;

// Create a diagonal linear gradient with four stops.   
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush();
myLinearGradientBrush.StartPoint = new Point(0,0);
myLinearGradientBrush.EndPoint = new Point(1,1);
myLinearGradientBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myLinearGradientBrush.GradientStops.Add(new GradientStop(Colors.Red, 0.25));                
myLinearGradientBrush.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));        
myLinearGradientBrush.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Use the brush to paint the rectangle.
diagonalFillRectangle.Fill = myLinearGradientBrush;
3
Andrej B. On

If you want to use brushes in XAML, maybe DataTrigger is what you want.

With triggers you can change styles dynamically. In this example I'm changing rectangle fill property, based on Priority property value:

 <Grid>
  <Grid.Resources>

    <LinearGradientBrush x:Key="HighPriorityBrush" EndPoint="1,0.5" StartPoint="0,0.5">
      <GradientStop Color="DarkRed" />
      <GradientStop Color="Orange" Offset="1" />
    </LinearGradientBrush>

    <LinearGradientBrush x:Key="NormalPriorityBrush" EndPoint="1,0.5" StartPoint="0,0.5">
      <GradientStop Color="Orange" />
      <GradientStop Color="Yellow" Offset="0.5" />
      <GradientStop Color="Lime" Offset="1" />
    </LinearGradientBrush>

    <LinearGradientBrush x:Key="LowPriorityBrush" EndPoint="1,0.5" StartPoint="0,0.5">
      <GradientStop Color="Lime" />
      <GradientStop Color="Green" Offset="1" />
    </LinearGradientBrush>
  </Grid.Resources>

    <Rectangle Height="150" Width="150">
      <Rectangle.Style>
        <Style TargetType="Rectangle">
          <Style.Triggers>
            <DataTrigger Binding="{Binding Priority}" Value="0">
              <Setter Property="Fill" Value="{StaticResource LowPriorityBrush}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Priority}" Value="1">
              <Setter Property="Fill" Value="{StaticResource NormalPriorityBrush}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Priority}" Value="2">
              <Setter Property="Fill" Value="{StaticResource HighPriorityBrush}" />
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </Rectangle.Style>
    </Rectangle>
   </Grid>

And Priority property from ViewModel returns something like this:

private double realPriority; // your priority
public double Priority
{
  get
  {
    if (this.realPriority < -0.5) return 0;
    if (this.realPriority > 0.5) return 2;
    return 1;
  }
}
0
Lumo On

You could create a converter to convert a number into a Brush:

public class NumberToBrushConverter : MarkupExtension, IValueConverter
{
    private static object instance;
    public override object ProvideValue(IServiceProvider serviceProvider) { if (instance == null) { instance = Activator.CreateInstance(GetType()); } return instance; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double aNumber = (double)value;

        // Define your gradient colors depending on the number

        return new System.Windows.Media.LinearGradientBrush(aColor1, aColor2, 
                new System.Windows.Point(0, 0), new System.Windows.Point(1, 0));
    }

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

Then use it in your XAML binding:

<Border Background="{Binding YourVM.Number, Converter={yournamespace:NumberToBrushConverter}}" />
0
Amin AmiriDarban On
using System;
using System.Windows.Media;
using SDColor = System.Drawing.Color;

//Developed by امین امیری دربان
namespace APREndUser.CodeAssist
{
    public static class ColorHelper
    {
      public static SDColor ToSDColor(SWMColor color) => SDColor.FromArgb(color.A, color.R, color.G, color.B);
      public static Tuple<SDColor, SDColor> GetColorFromRYGGradient(double percentage)
        {
            var red = (percentage > 50 ? 1 - 2 * (percentage - 50) / 100.0 : 1.0) * 255;
            var green = (percentage > 50 ? 1.0 : 2 * percentage / 100.0) * 255;
            var blue = 0.0;
            SDColor result1 = SDColor.FromArgb((int)red, (int)green, (int)blue);
            SDColor result2 = SDColor.FromArgb((int)green, (int)red, (int)blue);
            return new Tuple<SDColor, SDColor>(result1, result2);
        }
    }

}