Как связать цвета GradientStop или свойство GradientStops в Silverlight? - PullRequest
4 голосов
/ 03 октября 2009

Я хочу иметь динамический градиент в 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, у нее также будет та же проблема, что решение этой проблемы:

  1. Позволяет изменять начало и конец градиента во время выполнения
  2. Работает в Silverlight 3.0 и не является решением WPF

Если есть обходной путь или в любом случае для дублирования этого поведения, это было бы приемлемо, у меня есть решения, которые работают с LinearGradients, так как я могу просто привязать кое-что свойство "Fill" к этому - однако в этой ситуации это не будет работать плюс могут быть другие типы градиентов, которые я могу использовать, и другие могут использовать в будущем, к которым будет применяться это решение / альтернатива.

Ответы [ 4 ]

12 голосов
/ 04 октября 2009

Проблема в том, что GradientStop не является производным от FrameworkElement , поэтому не может быть привязан к данным. К сожалению, это означает, что вы должны установить его из кода.

5 голосов
/ 04 октября 2009

Чтобы действительно это произошло, у вас есть два варианта.

Привязка отображаемых элементов Свойство 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;
}

Протест

Всякий раз, когда происходит связывание данных, создается целая куча кистей по одной для каждого элемента. Это может быть дорого и нежелательно. Следовательно, если этот подход с привязкой к конвертеру будет сочтен необходимым, я рекомендую вам использовать статический словарь кистей. Ключом в этом словаре будет хэш двух цветов. Вы будете создавать новую кисть только при необходимости и повторно использовать ранее созданную кисть, когда это возможно.

0 голосов
/ 17 марта 2015

Довольно старый пост, но это возможно (сейчас), так что вот мое решение. Мой 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;
    }
}
0 голосов
/ 03 октября 2009

Подтвердили ли вы тип, используемый как DataContext, где определена ваша кисть градиента? Поскольку вы не указали Source в привязке, он будет использовать DataContext по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...