在WPF中动态更改样式

20
有没有办法在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>
  1. 如何实现将Pink颜色更改为Green且所有样式为MyLineStyleKey的线变为绿色?当线条被释放时它是粉色,被选中时是蓝色... 现在,我需要更改未选定状态下的属性(从粉色到绿色)..., 所以这不仅仅是将其设置为另一种颜色,触发器(选中> 蓝色)将不再起作用... 是否有可能?如何实现?

  2. 是否可以将按钮背景与样式中的Pink颜色绑定,以反映当前使用的样式颜色?

编辑:
对于1,我尝试过:

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

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

但是出现了一个异常:

'SetterBase'一旦被使用(sealed),就不能再被修改。


可能会动态地完成。 - Wernight
2个回答

29

创建一个作为资源的画刷

<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,则不会获得此行为。


一个问题:我能否将DynamicBrush传递给WPF用户控件? - serhio
我不知道你所说的“Pass”是什么意思,但你肯定可以从用户控件中引用它,即使它是在层次结构中更高的控件上定义的(比如在窗口上)。 - Isak Savo
这个解决方案可能会解决问题,但它并没有确切回答所问的问题。 - peter70

22

在第一次使用样式之前,可以修改样式。根据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));

哦...我有一个带触发器的样式...当释放时,一行是粉色的,选中时是蓝色的...现在,我需要更改未选中的属性...因此,这不仅仅是将其设置为另一种颜色,触发器(选择>蓝色)将不再起作用... - serhio
嗯...我想,如果我将所有行从样式中分离出来,一旦使用后就无法修改它了... - serhio
这是正确的解决方案,完全回答了所提出的问题。 - peter70

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接