Change a style dynamically in WPF
Solution 1
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:
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 DynamicResource
for the brush reference in your style - this tells WPF to monitor that resource for changes. If you use a StaticResource
instead, you won't get this behavior.
Solution 2
A style can only be modified before its first use. From 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));
serhio
I like .NET and started learning PHP. email: gserhio[at]gmail[.]com
Updated on July 09, 2022Comments
-
serhio almost 2 years
Is there a way to change(and apply) a style dynamically in WPF?
Say I have the style declared in 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>
In a moment, I need to change the
Pink
color, to, sayGreen
, and all lines with styleMyLineStyleKey
became 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?Is that possible to bind to the Pink color in the Style, say, to a Button background, that will reflect the currently used style color?
EDIT:
For 1 I tried: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.
-
serhio over 13 yearsoh... I has a style with a trigger... A line was Pink when released, and Blue when selected... Now, I needed to change the unselected property..., so this is not just setting it to an other color, the trigger (selection>Blue) will not work anymore...
-
serhio over 13 yearshm... I suppose, if I will detach all lines from the style, I will not however be able to modify it, once used...
-
serhio over 13 yearsA question: Can I pass a dynamicBrush to a WPF userControl?
-
Isak Savo over 13 yearsI don't know what you mean with "Pass" but you can certainly reference it from your user control even it is defined on a control higher up in the hierarchy (like on the window).
-
peter70 about 8 yearsThis solution may solve the problem, but it does not answer exactly the asked question
-
peter70 about 8 yearsThis is the right solution, that answers exactly the asked question