100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

Theming with XAML

Learn how to structure XAML resource dictionaries to support light/dark theming, runtime theme switching, and consistent theme resource naming.

Resources and StylingAdvanced10 min readJul 10, 2026
Analogies

Theme Resource Dictionaries

XAML theming is built on the same resource dictionary infrastructure used for regular styling: each theme (Light, Dark, HighContrast) is expressed as its own ResourceDictionary file defining brushes, colors, and sometimes styles under a fixed, shared set of keys, so consuming controls never reference a theme-specific key directly but always reference the common name, such as SurfaceBrush or PrimaryTextBrush. Swapping the active theme then becomes a matter of swapping which theme dictionary is merged into the application, rather than changing anything in the controls that consume those resources.

🏏

Cricket analogy: It is like a team having interchangeable day and pink-ball kit sets that both map to the same named roles (opener's kit, keeper's gloves), so players just grab 'the keeper's gloves' and get whichever set is currently in use for that match.

csharp
public static void ApplyTheme(string themeName)
{
    var dictionaries = Application.Current.Resources.MergedDictionaries;

    var existingTheme = dictionaries.FirstOrDefault(d =>
        d.Source != null && d.Source.OriginalString.Contains("/Themes/"));

    if (existingTheme != null)
        dictionaries.Remove(existingTheme);

    var newTheme = new ResourceDictionary
    {
        Source = new Uri($"/DemoApp;component/Themes/{themeName}.xaml", UriKind.Relative)
    };

    dictionaries.Add(newTheme);
}

// ApplyTheme("Dark");  swaps every DynamicResource-bound brush at once

Dynamic Theme Switching

For theme swapping to work visually without reloading windows, every control property that depends on a theme brush or color must reference it with {DynamicResource ...} rather than {StaticResource ...}, since only DynamicResource maintains a live link that re-resolves when the resource dictionary entry changes; a StaticResource-bound Background would keep showing the old theme's color until the window is torn down and recreated. This is one of the few places in XAML where the small extra overhead of DynamicResource is clearly worth paying, because the alternative is a jarring, incomplete theme switch.

🏏

Cricket analogy: It is like a scoreboard operator who must manually re-key every number for a fresh display versus a fully automated electronic scoreboard that updates live the instant a run is scored; only the automated version reflects change in real time, just as only DynamicResource does for themes.

Theme Resource Keys and Naming Conventions

A robust theming setup relies on a consistent, semantic naming convention for keys — names like SurfacePrimaryBrush, TextOnSurfaceBrush, and BorderSubtleBrush describe the resource's role rather than its literal color, so that Light.xaml, Dark.xaml, and HighContrast.xaml can each provide a different Color for the same semantically named key. Naming brushes after a literal color, like Gray200Brush, defeats the purpose of theming, because a dark theme's 'gray 200' equivalent is usually not literally gray, and controls referencing color-literal names end up needing per-theme conditional logic instead of a clean resource swap.

🏏

Cricket analogy: It is like naming a fielding position by its tactical role, such as 'short cover' or 'deep midwicket,' rather than by which specific player currently stands there, so the role name stays meaningful even as the actual fielder assigned to it changes between overs.

WPF and UWP both support ResourceDictionary.ThemeDictionaries, a special collection keyed by theme name (Light, Dark, HighContrast) that the framework consults automatically based on the OS or app theme setting, letting you provide theme-specific brushes without writing your own theme-switching code for the common case.

Persisting and Applying User Theme Choice

For an explicit in-app theme toggle (as opposed to following the OS setting), the chosen theme name should be persisted to application settings or user preferences and applied as early as possible during startup, ideally before the main window is constructed, so the user never sees a flash of the wrong theme. Runtime toggling then reuses the same merge-and-swap logic shown earlier, updating the MergedDictionaries collection and persisting the new choice immediately so the next launch starts in the correct theme without any additional migration logic.

🏏

Cricket analogy: It is like a team deciding the toss strategy and communicating it to every player before they walk onto the field, rather than changing the plan mid-over, so no one is caught out of position when play begins.

If a resource key exists in one theme dictionary but is missing from another (for example, an AccentGlowBrush added only to Dark.xaml), switching to the theme that lacks it will throw a XamlParseException or resolve to null for any DynamicResource reference, so every theme dictionary must define the full, identical set of semantic keys.

  • Theming reuses ResourceDictionary infrastructure, with each theme providing the same semantic keys.
  • Switching themes means swapping which theme dictionary is merged into the application's resources.
  • DynamicResource, not StaticResource, is required for properties to update live during a theme swap.
  • Semantic key naming (role-based, not color-literal) keeps theme dictionaries interchangeable.
  • ThemeDictionaries lets WPF/UWP auto-select Light/Dark/HighContrast based on OS settings.
  • Persisted theme choice should be applied before the main window is constructed to avoid a flash.
  • Every theme dictionary must define the same complete set of keys to avoid missing-resource errors.

Practice what you learned

Was this page helpful?

Topics covered

#NET#XAMLStudyNotes#MicrosoftTechnologies#ThemingWithXAML#Theming#XAML#Theme#Resource#StudyNotes#SkillVeris