在 WPF 中动态更改样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3821573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:09:56  来源:igfitidea点击:

Change a style dynamically in WPF

wpfstyles

提问by serhio

Is there a way to change(and apply) a style dynamically in WPF?

有没有办法在 WPF 中动态更改(和应用)样式?

Say I have the style declared in XAML:

假设我在 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>
  1. In a moment, I need to changethe Pinkcolor, to, say Green, and all lines with style MyLineStyleKeybecame Green. A line is Pink when released, and Blue when selected... Now, I needed to change the unselected property(Pink to Green)..., so this is not just setting it to an other color, the trigger (selection>Blue) will not work anymore...Is that possible? How?

  2. Is that possible to bindto the Pink color in the Style, say, to a Button background, that will reflect the currently used style color?

  1. 稍后,我需要将颜色更改Pink为,例如Green,所有带有样式的线条都MyLineStyleKey变为绿色。释放时一条线是粉红色,选中时为蓝色...现在,我需要更改未选中的属性(粉红色到绿色)...,所以这不仅仅是将其设置为其他颜色,触发器(选择>蓝色) ) 将不再起作用......这可能吗?如何?

  2. 是否可以绑定到样式中的粉红色,例如按钮背景,以反映当前使用的样式颜色?

EDIT:
For 1I tried:

编辑:
对于1我试过:

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

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

but an exception occured:

但是出现了异常:

After a 'SetterBase' is in use (sealed), it cannot be modified.

'SetterBase' 使用(密封)后,将无法修改。

回答by Isak Savo

Create a brush as a resource

创建画笔作为资源

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

and refer to that in your style

并以你的风格参考

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

Now to change the color of all shapes that use the "MyShapeStyle" style, you can do the following from your code-behind:

现在要更改使用“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)));
}

The thing that makes this work is the fact that you use a DynamicResourcefor the brush reference in your style - this tells WPF to monitor that resource for changes. If you use a StaticResourceinstead, you won't get this behavior.

使这项工作有效的原因是您DynamicResource在样式中使用了画笔参考 - 这告诉 WPF 监视该资源的更改。如果您使用 aStaticResource代替,您将不会得到这种行为。

回答by Thomas Levesque

A style can only be modified before its first use. From MSDN:

样式只能在第一次使用之前修改。来自 MSDN:

A style is sealed when another style is based on it or when it is applied for the first time.

当另一种样式基于它或第一次应用时,该样式将被密封。

Instead, you could create a new style based on your existing style, and override the properties you want:

相反,您可以根据现有样式创建新样式,并覆盖所需的属性:

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