Динамически изменять стиль в WPF

Есть ли способ динамически изменять (и применять) стиль в WPF?

Скажем, у меня есть стиль, объявленный в XAML:

    <Style TargetType="local:MyLine" 
           x:Key="MyLineStyleKey" x:Name="MyLineStyleName">
        <Setter Property="Fill" Value="Pink"/>
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="true">
                <Setter Property="Fill" Value="Blue" />                    
            </Trigger>
        </Style.Triggers>
    </Style>
  • В какой-то момент мне нужно изменить цвет Pink, скажем Green, а все строки со стилем MyLineStyleKey стали зелеными. Линия розовая, когда ее отпускают, а синий - когда выбрано... Теперь мне нужно было изменить невыбранное свойство (от Pink до Green)..., так что это не просто настройка его на другой цвет, триггер (выбоp > синий ) больше не будет работать... Это возможно? Как?

  • Возможно ли привязать к розовому цвету в стиле, скажем, к фону кнопки, который будет отражать используемый в текущий момент цвет стиля?

EDIT:
Для 1 я попробовал:

Style s = (Style)this.Resources["MyLineStyleKey"];

(s.Setters[0] as Setter).Value = background;
(s.Setters[1] as Setter).Value = background;

но произошло исключение:

После использования "SetterBase" (запечатан), он не может быть изменен.

Ответы

Ответ 1

Создайте кисть в качестве ресурса

<SolidColorBrush x:Key="MyFillBrush" Color="Pink" />

и обратитесь к этому в своем стиле

<Style x:Key="MyShapeStyle" TargetType="Shape">
    <Setter Property="Fill" Value="{DynamicResource MyFillBrush}" />
</Style>
...
<!-- Then further down you may use it like this -->
<StackPanel Width="100">
    <Rectangle Style="{StaticResource MyShapeStyle}" Height="50" Margin="8" />
    <Rectangle Style="{StaticResource MyShapeStyle}" Height="50" Margin="8" />
    <Ellipse Style="{StaticResource MyShapeStyle}" Height="50" Margin="8" />
    <Button Content="Click to change color" Click="Button_Click" Margin="8" />
</StackPanel>

Теперь, чтобы изменить цвет всех фигур, которые используют стиль "MyShapeStyle", вы можете сделать следующее из кода:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Random r = new Random();
    this.Resources["MyFillBrush"] = new SolidColorBrush(Color.FromArgb(
          0xFF, 
          (byte)r.Next(255), 
          (byte)r.Next(255), 
          (byte)r.Next(255)));
}

То, что делает эту работу, состоит в том, что вы используете DynamicResource для ссылки на кисть в своем стиле - это говорит WPF контролировать этот ресурс для изменений. Если вместо этого вы используете StaticResource, вы не получите этого поведения.

Ответ 2

Стиль может быть изменен только до его первого использования. Из MSDN:

Стиль запечатан, когда другой стиль основан на нем или когда он применяется в первый раз.

Вместо этого вы можете создать новый стиль на основе существующего стиля и переопределить нужные свойства:

Style newStyle = new Style();
newStyle.BasedOn = originalStyle;
newStyle.TargetType = typeof(MyLine);
Brush blue = new SolidColorBrush(Colors.Blue);
newStyle.Setters.Add(new Setter(Shape.FillProperty, blue));
newStyle.Setters.Add(new Setter(Shape.StrokeProperty, blue));