6

我希望能够在 Silverlight 中拥有动态渐变,如下所示:

<RadialGradientBrush GradientOrigin="0.20,0.5" Center="0.25,0.50" 
                     RadiusX="0.75" RadiusY="0.5">
  <GradientStop Color="{Binding Path=GradientStart}" Offset="0" />
  <GradientStop Color="{Binding Path=GradientEnd}" Offset="1" />
</RadialGradientBrush>

我绑定到两个返回“颜色”类型的属性,但是我总是收到此消息:

AG_E_PARSER_BAD_PROPERTY_VALUE

如果我尝试绑定到 GradientStop Collection 这也有同样的问题,这个问题的解决方案是什么:

  1. 允许在运行时更改渐变的开始和结束
  2. 在 Silverlight 3.0 中工作,不是 WPF 解决方案

如果有解决方法或无论如何要复制此行为,这是可以接受的,我有与 LinearGradients 一起使用的解决方案,因为我可以将某些“填充”属性绑定到此 - 但是在这种情况下不起作用,而且可能是我可能使用的其他渐变类型,以及将来可能使用的其他渐变类型,此解决方案/替代方案将适用。

4

4 回答 4

14

问题是GradientStop不是从FrameworkElement派生的,因此不能进行数据绑定。不幸的是,这意味着您必须从代码中设置它。

于 2009-10-03T20:13:41.403 回答
5

要真正做到这一点,您有两个选择。

将显示项的 Brush 属性绑定到数据中的 Brush 属性

让数据源携带一个属性,该属性公开您要为每个项目使用的画笔,然后绑定使用画笔的显示项目的属性,比如一个Fill属性。如果您对 Start 和 Stop 值对的不同值集很小,则此方法有效。您将为每一对画笔创建一个实例,然后数据项将显示正确的画笔。

使用值转换器绑定显示项 Brush 属性

如果您的 Start 和 Stop 值更多变量,您将需要为每个显示的项目创建一个 Brush 类型的新实例。在这种情况下,您将使用值转换器绑定显示项目画笔属性,例如:-

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

有关构建转换器的完整描述,请参阅此答案。

在这种情况下,虽然您的转换方法实现看起来像这样:-

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;
}

警告

每当发生数据绑定时,都会为每个项目创建一大堆画笔。这可能是昂贵且不受欢迎的。因此,如果认为这种绑定转换器方法是必要的,那么我建议您使用静态画笔字典。这个字典的关键是这两种颜色的哈希值。您只会在必要时创建一个新画笔,并尽可能重复使用以前创建的画笔。

于 2009-10-04T13:50:28.530 回答
0

您是否已确认用作DataContext定义渐变画笔的类型?由于您没有Source在绑定中指定 a,因此默认情况下它将使用DataContext

于 2009-10-03T15:02:34.613 回答
0

很老的帖子,但有可能(现在),所以这是我的解决方案。我的 XAML 代码:

<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>

这是我的 C# 代码。

[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;
    }
}
于 2015-03-17T09:39:51.817 回答