如何在Silverlight中绑定GradientStop Colors或GradientStops属性?

发布于 2024-08-07 01:46:43 字数 740 浏览 3 评论 0原文

我希望能够在 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>

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

AG_E_PARSER_BAD_PROPERTY_VALUE

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

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

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

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

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

I am binding to two properties which return the type "Color" however I always get this message:

AG_E_PARSER_BAD_PROPERTY_VALUE

If I try to bind to a GradientStop Collection this also has the same problem, what is the solution to this problem that:

  1. Allows the start and end of a Gradient to be changed at runtime
  2. Works in Silverlight 3.0 and is not a WPF solution

If there is a work around or anyway to duplicate this behaviour this would be acceptable, I have solutions that work with LinearGradients as I can just bind somethings "Fill" property to this - however in this situation that won't work, plus there may be other gradient types I may use and others may use in future which this solution / alternative will apply to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

⒈起吃苦の倖褔 2024-08-14 01:46:43

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

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.

°如果伤别离去 2024-08-14 01:46:43

要真正实现这一目标,您有两种选择。

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

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

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

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

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

请参阅此 answer 了解构建转换器的完整说明。

在这种情况下,您的转换方法实现将如下所示: -

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

警告

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

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.

眼泪都笑了 2024-08-14 01:46:43

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

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.

土豪我们做朋友吧 2024-08-14 01:46:43

很旧的帖子,但这是可能的(现在),所以这是我的解决方案。我的 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;
    }
}

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文