How to bind GradientStop Colours or GradientStops Property in Silverlight?

前端 未结 4 880
情书的邮戳
情书的邮戳 2020-12-11 18:41

I want to be able to have a dynamic Gradient in Silverlight, such as below:



        
相关标签:
4条回答
  • 2020-12-11 19:13

    To really make this happen you have two choices.

    Bind the display items Brush property to a Brush property in the data

    Have the data source carry a property which exposes which brush you want to use on for each item and you bind the property of the display item that takes the brush, say a Fill property. This works if the set of distinct values you would have for pairs of Start and Stop values is small. You'd create an instance of each brush for each pair and then data item would expose the correct one.

    Bind the display items Brush property using a Value Converter

    If your Start and Stop values a more variable you will need a new instance of a Brush type for each displayed item. In this case you would bind the display items brush property using a Value converter, for example :-

     <Rectangle Fill="{Binding Converter={StaticResource MyBrushBuilder} }" ... >
    

    See this answer for a complete description of building a Converter.

    In this case though your convert method implementation would look like this:-

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      YourItemsType item = (YourItemsType)value;
    
      var start = new GradientStop();
      start.Offset = 0;
      start.Color = item.GradientStart;
    
      var stop = new GradientStop();
      stop.Offset = 1;
      stop.Color = item.GradientStop;
    
      var result = new RadialGradientBrush();
      result.GradientOrigin = new Point(0.20, 0.5);
      result.Center = new Point(0.25, 0.5);
      result.RadiusX = 0.75;
      result.RadiusY = 0.5;
      result.GradientStops = new GradientStopCollection();
      result.GradientStops.Add(start);
      result.GradientStops.Add(stop);
    
      return result;
    }
    

    Caveat

    Whenever data binding occurs a whole bunch of brushes are created one for each item. This may be expensive and undesirable. Hence if this binding converter approach is deemed necessary then I would recommend you use static dictionary of brushes. The key into this dictionary would be the hash of the two colors. You would only create a new brush when necessary and reuse a previously created brush when possible.

    0 讨论(0)
  • 2020-12-11 19:22

    Have you confirmed the type being used as the DataContext where your gradient brush is defined? As you haven't specified a Source in your binding, it will use the DataContext by default.

    0 讨论(0)
  • 2020-12-11 19:24

    Pretty old Post, but it's possible (now), so here is my solution. My XAML-Code:

    <Ellipse.Resources>
        <local:ColorConverter x:Key="ColorConverter"/>
    </Ellipse.Resources>
    <Ellipse.Fill>
        <RadialGradientBrush>
            <GradientStop Color="{Binding MenuColor2, Source={x:Static p:Settings.Default}, Converter={StaticResource ColorConverter}}" Offset="1" />
            <GradientStop Color="{Binding MenuColor1, Source={x:Static p:Settings.Default}, Converter={StaticResource ColorConverter}}" Offset="0.85" />
        </RadialGradientBrush>
    </Ellipse.Fill>
    

    And here is my C#-Code.

    [ValueConversion(typeof(System.Drawing.Color), typeof(System.Windows.Media.Color))]
    public class ColorConverter : IValueConverter
    {
    
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is System.Drawing.Color)
            {
                var clr = (System.Drawing.Color)value;
                return System.Windows.Media.Color.FromArgb(clr.A, clr.R, clr.G, clr.B);
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Color)
            {
                var clr = (Color)value;
                return System.Drawing.Color.FromArgb(clr.A, clr.R, clr.G, clr.B);
            }
            return value;
        }
    }
    
    0 讨论(0)
  • 2020-12-11 19:34

    The problem is that GradientStop does not derive from FrameworkElement therefore cannot be data bound. Unfortunately that means you have to set it from code.

    0 讨论(0)
提交回复
热议问题