Iris Classon
Iris Classon - In Love with Code

Example WinRT: Changing existing style resource at runtime in code using databindings

I’ve noticed that the last how to change style during runtime example I posted is rather popular, and earlier today I was trying to help somebody with a TextBlock style change implementation for a Windows Store App. The difference this time was that we wanted to change an existing style, not just switch styles. Wether or not that is a good idea is a discussion on its own (and depends on the scenario).

Nontheless, here is a quick sample for a MVVM friendly implementation for how to change an existing style resource (defined in a resource dictionary) at runtime.

View:

[sourcecode language=“XML”]






[/sourcecode]

The style defined at /Common/StandardStyles.xaml

[sourcecode language=“XML”]





[/sourcecode]

The code:

[sourcecode language=“csharp”]
public sealed partial class MainPage : INotifyPropertyChanged
{
private Style _fontStyleText;
public Style FontStyleText
{
get { return this._fontStyleText; }

        set  
        {  
            if (value == this.\_fontStyleText) return;  
            this.\_fontStyleText = value;  
            NotifyPropertyChanged();  
        }  
    }  

    private List<string> \_fonts;  
    public List<string> Fonts  
    {  
        get { return this.\_fonts; }  

        set  
        {  
            if (value == this.\_fonts) return;  
            this.\_fonts = value;  
            NotifyPropertyChanged();  
        }  
    }  

    public MainPage()  
    {  
        this.InitializeComponent();  
        DataContext = this;  

        Fonts = new List<string> {"Segoe UI", "Showcard Gothic", "Arial"};  

        FontStyleText = Application.Current.Resources["textStyle"] as Style;  

    }  

    private void ListBox\_SelectionChanged\_1(object sender, SelectionChangedEventArgs e)  
    {  
        var font = (sender as ListBox).SelectedItem as string;  

        var res = new ResourceDictionary { Source = new Uri("ms-appx:///Common/StandardStyles.xaml", UriKind.Absolute)};  

        var style = res["textStyle"] as Style;  

        style.Setters.RemoveAt(0); // if it is the first item otherwise for more accurat removal se below  

        foreach (var item in style.Setters.Cast<Setter>().Where(item => item.Property == FontFamilyProperty))  
            style.Setters.Remove(item);  

        style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, new FontFamily(font)));  
        style.Setters.Add(new Setter(TextBlock.ForegroundProperty, new SolidColorBrush(Colors.Yellow)));  

        FontStyleText = style;  
    }  

    public event PropertyChangedEventHandler PropertyChanged;  
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")  
    {  
        if (PropertyChanged != null)  
        {  
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
        }  
    }  
}  

[/sourcecode]

Comments

Leave a comment below, or by email.
Thierry
5/12/2014 2:33:21 AM
Hello,
your sample works well, but in Win8.1, when I try to debug it, there is no item which match the request in the foreach. Furthermore, there is 2 FontFamily setter in the style after the changes...
Is there another way to compare the setter object ?
Regards
Thierry 
Iris Classon
5/12/2014 4:48:46 AM
Reply to: Thierry
Hi Thierry! Let me have a look at this tomorrow and I'll try to sort it out. I have to admit I haven't used the code in Win8.1 - but how annoying behavior is changed! Will ping you once I figure it out, unless you beat me to it ;) 
Thierry
5/12/2014 5:04:35 AM
Reply to: Iris Classon
Hi Iris !,
I finally found the problem... in fact, the only missing thing is the TextBlock prefix on the where clause like : 
Where (item => item.Property == TextBlock.FontFamilyProperty)
Now it works well and there is only one FontFamily in the Setter collection. 


Last modified on 2013-01-04

comments powered by Disqus