Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing XAML style dynamically in Code Behind so that controls applying that style also reflect the change

Tags:

c#

styles

wpf

I want to be able to set style properties (and values) from the .cs file in my WPF window.

My problem is if I have 30 rectangles, all of which I want to have the same style (and I don't want to update all of them individually). I'd like to have them all set (in the xaml file) to the same style, and then update the style to look the way I'd like.

Say I set the Style = "key1" in the Xaml for each rectangle. Then I want to be able to modify "key1" later so all the rectangles will reflect that change.

I tried in App.xaml

<Application.Resources>
    <Style x:Key="key1" TargetType="Rectangle">
        <Setter Property="Fill" Value="Red"/>
    </Style>
</Application.Resources>

In MainwWindows.xaml

<StackPanel>
    <Rectangle Style="{StaticResource key1}" Height="200" Width="200" x:Name="rect1"/>
    <Button Click="Button_Click" Content="Click"/>
</StackPanel>

In code behind

private void Button_Click(object sender, RoutedEventArgs e)
{
    Style style = Application.Current.Resources["key1"] as Style;
    style.Setters.Add(new Setter(Rectangle.VisibilityProperty, Visibility.Collapsed));
}

This updates the style but do not update the rectangles.

Is this possible? Does anyone know how to do this? (An example would be greatly appreciated).

like image 910
Nikhil Agrawal Avatar asked Apr 27 '12 05:04

Nikhil Agrawal


People also ask

How do I apply styles in XAML?

Apply a style implicitly You can change the default appearance by setting properties, such as FontSize and FontFamily, on each TextBlock element directly. However, if you want your TextBlock elements to share some properties, you can create a Style in the Resources section of your XAML file, as shown here.

What is style in XAML?

You can customize the appearance of your apps in many ways by using the XAML framework. Styles let you set control properties and reuse those settings for a consistent appearance across multiple controls.

Can style be inherited or extended in WPF?

WPF provides a way to inherit the style by another one. BasedOn property helps us to achieve this.


3 Answers

You need to use DynamicResource so that it can be changed at run-time. You also need to replace the style with a new one, not try to modify the existing one. This works:

<StackPanel>
    <Rectangle Style="{DynamicResource key1}" Height="200" Width="200" x:Name="rect1"/>
    <Button Click="Button_Click" Content="Click"/>
</StackPanel>

Style style = new Style {TargetType = typeof(Rectangle)};
style.Setters.Add(new Setter(Shape.FillProperty, Brushes.Red));
style.Setters.Add(new Setter(UIElement.VisibilityProperty, Visibility.Collapsed));

Application.Current.Resources["key1"] = style;
like image 175
Phil Avatar answered Nov 17 '22 22:11

Phil


It is also worth mentioning that styles are sealed once used and hence can not be changed. This is the reason why styles should be replaced by another instance rather than updated.

like image 38
Ahmad Avatar answered Nov 17 '22 20:11

Ahmad


Created some static helpers, usage example:

SetStyle(typeof(ContentPage), 
   (ContentPage.BackgroundColorProperty, Color.Green), 
   (ContentPage.PaddingProperty, new Thickness(20)));

Helper methods:

    public static Style CreateStyle(Type target, params (BindableProperty property, object value)[] setters)
    {
        Style style = new Style(target);
        style.ApplyToDerivedTypes = true;
        foreach (var setter in setters)
        {
            style.Setters.Add(new Setter
            {
                Property = setter.property,
                Value = setter.value
            });
        }
        return style;
    }

    public static void SetStyle(Type target, params (BindableProperty property, object value)[] setters)
    {
        Style style = new Style(target);
        style.ApplyToDerivedTypes = true;
        foreach (var setter in setters)
        {
            style.Setters.Add(new Setter
            {
                Property = setter.property,
                Value = setter.value
            });
        }
        Application.Current.Resources.Add(style);
    }
like image 1
Nick Kovalsky Avatar answered Nov 17 '22 21:11

Nick Kovalsky