Search code examples
xamlwindows-store-appswindows-8.1winrt-xaml

Runtime change Resource Dictionary for a Windows 8.1 XAML Store App


I am trying to dynamically change my resource dictionary definitions for my application during run time.

I am doing this because I would like to have different font sizes, scaling etc for my application based on the view port size.

I currently have the following code which gets executed every time the view port size changes:

string stylesPath;

if (args.Type == "small")
{
    stylesPath = "ms-appx:///Styles/small.xaml";
}
else
{
    stylesPath = "ms-appx:///Styles/standard.xaml";
}

var resourceDictionary = new ResourceDictionary
{
    Source = new Uri(stylesPath, UriKind.RelativeOrAbsolute)
};

Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);

This works for the initial load. When I change my view port this code does get hit again, but after the resources dictionaries are cleared and reloaded my application's fonts/styles/etc don't change at all.

It appears that the application styles will only be loaded once during application start up.

Does anyone know of a way I can force my application to redraw itself based on the new resource dictionary values?


Solution

  • This can be accomplished using Themes. There is a handy nuget package, called Theme Manager, that makes it very easy to switch themes.

    Instead of loading your themes on app load, put them in your app ThemeDictionaries

    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Dark">
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Themes/small.xaml"/>
                <ResourceDictionary Source="/Themes/standard.xaml"/>
            </ResourceDictionary.MergedDictionaries>
       </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
    

    Then you can change the theme like such:

    var url = new Uri(string.Format("ms-appx:///Themes/{0}.xaml", (args.Type == "small") ? "small" : "standard"));
    ThemeManager.ChangeTheme(url);
    

    You can read more about ThemeManager here.