Customizing Theme Colors in WinUI3 Applications

Changing Theme at Runtime

Setting the application theme programmatically is straightfowrard:

rootElement.RequestedTheme = ElementTheme.Dark;

This produces the same result as setting RequestedTheme="Dark" directly on a XAML element. However, there are important limitations:

  • Custom colors defined within a page cannot be overridden
  • Title bar colors remain unaffected by this approach

For instance, using a theme-aware brush like Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" locks the color, preventing runtime changes.

Understanding Resource Dictionaries

The Windows App SDK documentation on XAML resource dictionaries explains how to define reusable resources. When you need different colors for light and dark modes, resource dictionaries with ThemeDictionaries become essential.

Theme Dictionary Structure

Each ResourceDictionary inside ThemeDictionaries requires an x:Key attribute identifying the theme, such as "Light", "Dark", "Default", or "HighContrast".

Key Differences Between ThemeResource and StaticResource

The {ThemeResource} markup extension evaluates when the app loads and whenever the theme changes at runtime. In contrast, {StaticResource} is evaluated only during initial XAML parsing.

Important rules:

  • Use {ThemeResource} in styles, setters, control templates, property libraries, and animations
  • Inside ThemeDictionaries, use {StaticResource} instead of {ThemeResource}

Implementing Custom Theme Colors

Define theme-specific colors by creating separate resource dictionaries:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
        <SolidColorBrush x:Key="myBrush" Color="Red"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
        <SolidColorBrush x:Key="myBrush" Color="Blue"/>
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Reference these resources using ThemeResource for dynamic switching:

<TextBlock Foreground="{ThemeResource myBrush}" Text="hello world" VerticalAlignment="Center"/>

Complete Theme Selector Implementation

A common pattern uses a ComboBox to let users select themes:

<ComboBox x:Name="themeSelector" SelectionChanged="themeSelector_SelectionChanged">
    <ComboBoxItem Content="Light" Tag="Light" />
    <ComboBoxItem Content="Dark" Tag="Dark" />
    <ComboBoxItem Content="Use system setting" Tag="Default" />
</ComboBox>
private void themeSelector_SelectionChanged(object sender, RoutedEventArgs e)
{
    var selectedTheme = ((ComboBoxItem)themeSelector.SelectedItem)?.Tag?.ToString();
    var window = WindowHelper.GetWindowForElement(this);
    
    if (selectedTheme != null)
    {
        ThemeHelper.RootTheme = App.GetEnum<ElementTheme>(selectedTheme);
        
        if (selectedTheme == "Dark")
        {
            TitleBarHelper.SetCaptionButtonColors(window, Colors.White);
        }
        else if (selectedTheme == "Light")
        {
            TitleBarHelper.SetCaptionButtonColors(window, Colors.Black);
        }
        else
        {
            var systemColor = TitleBarHelper.ApplySystemThemeToCaptionButtons(window);
        }
    }
}

An alternative approach applies the theme directly to a container like SplitView:

var themeChoice = ((RadioButton)sender)?.Tag?.ToString();
if (themeChoice != null)
{
    ((sender as RadioButton).XamlRoot.Content as SplitView).RequestedTheme = 
        GetEnum<ElementTheme>(themeChoice);
}

Merged Resource Dictionaries

Organize resources across multiple files and merge them:

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Colors.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Page.Resources>

All resource require x:Key attributes. Styles targeting a TargetType with out a key automatically apply to matching controls.

Adding Resources Programmatically

Insert resources in Application.OnLaunched:

Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary 
{ 
    Source = new Uri("ms-appx:///Themes/CustomTheme.xaml") 
});

Custom Title Bar Styling

Title bar appearance is controlled by its own definition file. For complete customization, define the background color directly in the title bar XAML file rather than relying on external theme resources.

Tags: WinUI3 XAML Theme ResourceDictionary customization

Posted on Sun, 19 Jul 2026 17:04:06 +0000 by webster08