Overriding ThemeResources in Windows 8.1 Apps

Windows 8.1 offers a new markup extension called ThemeResource, this allows for dynamic theming of your app at runtime. There is also a new RequestedTheme property on FrameworkElement, which allows for retargeting specific islands of content. I was working on a sample today and wanted to write a short post to show how to put this all together with the combination of ThemeDictionaries to create a dynamic app.

ThemeResource

When you create a new Windows 8.1 app it behooves you use the built-in brushes and styles. This keeps your app consistent with the Windows experience, and also manages cases where users change their underlying system preferences for things like accessibility. Microsoft provides a reference of the XAML theme resources. To use them in Windows 8 you would just use a StaticResource.

<Border Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
</Border>

While StaticResource still works, with Windows 8.1, you can use the new ThemeResource markup extension for these references.

<Border Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
</Border>

This allows the resources to be updated dynamically whenever changes to the theme occur, previously this required an application restart. With the dynamic themes comes a broader reach for theme changing. To allow this, Microsoft added a RequestedTheme property to the FrameworkElement object. This allows you to change themes within the context of any element, even nested.

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <TextBlock Text="Default Theme" Foreground="{ThemeResource ApplicationForegroundThemeBrush}" />
    <StackPanel RequestedTheme="Light" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="Light Theme" Foreground="{ThemeResource ApplicationForegroundThemeBrush}" />
        <StackPanel x:Name="DarkContainer" RequestedTheme="Dark" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <TextBlock Text="DarkTheme" Foreground="{ThemeResource ApplicationForegroundThemeBrush}" />
        </StackPanel>
    </StackPanel>
</StackPanel>

You can also change these values at runtime in code.

DarkContainer.RequestedTheme = ElementTheme.Dark;

Overrides with ThemeDictionaries

You can override any of these existing styles by specifying a ResourceDictionary as part of the ThemeDictionaries. Each dictionary must specify a key with one of the following names:

  • Default
  • Dark
  • Light
  • HighContrast
  • HighContrastBlack
  • HighContrastWhite
  • HighContrastCustom

The ThemeDictionaries documentation provides all the rules, but the HighContrast key is the default for all high contrast options and the Default key is the fallback when a theme name that cannot be located. Inside the dictionary you can specify any resource override from the full list of theme resource keys.

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <SolidColorBrush x:Key="ApplicationPageBackgroundThemeBrush" Color="Magenta" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

There is one caveat that I notice in my samples, if you specify an ApplicationPageBackgroundThemeBrush, it’s best to specify the value for all themes, in my case Dark and Light. Until I made this change the Light theme wasn’t using the default white background brush I was looking for. This only seems to be an issue with the page background key, but this code fixed it

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Dark">
        <SolidColorBrush x:Key="ApplicationPageBackgroundThemeBrush" Color="Magenta" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="Light">
        <SolidColorBrush x:Key="ApplicationPageBackgroundThemeBrush" Color="#FFFFFFFF" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>