Skip to main content

ThemeVariantScope

The ThemeVariantScope control overrides the active theme variant (light or dark) for a section of your visual tree. All controls placed inside a ThemeVariantScope use the specified variant, regardless of the application or window setting. This is useful when you need part of your UI to display in a different theme from the rest of the application.

Common use cases​

  • Forcing a sidebar or panel to always render in dark mode while the rest of your app uses light mode.
  • Displaying a side-by-side preview of both theme variants on a settings page.
  • Creating contrasting regions in your layout for visual emphasis.

Useful properties​

PropertyTypeDescription
RequestedThemeVariantThemeVariantThe theme variant to apply within this scope. Values: Light, Dark, Default. Setting Default resets to the inherited variant.
ActualThemeVariantThemeVariantRead-only. The theme variant currently in effect within this scope.

Basic example​

You can force a section of the UI to use the light theme while the rest of the window uses the dark theme:

<Window RequestedThemeVariant="Dark">
<StackPanel Spacing="8" Margin="16">
<Button Content="Dark-themed button" />

<ThemeVariantScope RequestedThemeVariant="Light">
<StackPanel Spacing="8">
<Button Content="Light-themed button" />
<TextBox PlaceholderText="Light-themed input" />
</StackPanel>
</ThemeVariantScope>
</StackPanel>
</Window>

Side-by-side theme preview​

A common use case is displaying both theme variants at the same time, for example on a theme settings page:

<Grid ColumnDefinitions="*,*" Margin="16">
<ThemeVariantScope Grid.Column="0" RequestedThemeVariant="Light">
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
Padding="16" CornerRadius="8">
<StackPanel Spacing="8">
<TextBlock Text="Light Theme" FontWeight="SemiBold" />
<Button Content="Sample Button" />
<CheckBox Content="Sample Checkbox" IsChecked="True" />
<Slider Value="60" />
</StackPanel>
</Border>
</ThemeVariantScope>

<ThemeVariantScope Grid.Column="1" RequestedThemeVariant="Dark">
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
Padding="16" CornerRadius="8">
<StackPanel Spacing="8">
<TextBlock Text="Dark Theme" FontWeight="SemiBold" />
<Button Content="Sample Button" />
<CheckBox Content="Sample Checkbox" IsChecked="True" />
<Slider Value="60" />
</StackPanel>
</Border>
</ThemeVariantScope>
</Grid>

Resetting to the inherited variant​

Set RequestedThemeVariant="Default" to clear the override and inherit the variant from the parent scope:

<ThemeVariantScope RequestedThemeVariant="Light">
<StackPanel>
<!-- These use the Light variant -->
<Button Content="Light" />

<ThemeVariantScope RequestedThemeVariant="Default">
<!-- These inherit from the window/application -->
<Button Content="Inherited" />
</ThemeVariantScope>
</StackPanel>
</ThemeVariantScope>

Nesting scopes​

You can nest ThemeVariantScope controls to create multiple themed regions. Each scope resolves its variant independently, so a child scope overrides whatever its parent scope set:

<ThemeVariantScope RequestedThemeVariant="Dark">
<!-- Everything here uses the dark variant -->
<StackPanel Spacing="8">
<Button Content="Dark button" />

<ThemeVariantScope RequestedThemeVariant="Light">
<!-- This region switches to light -->
<Button Content="Light button inside dark scope" />
</ThemeVariantScope>
</StackPanel>
</ThemeVariantScope>

Theme-aware resources​

Resources defined in ThemeDictionaries respond to ThemeVariantScope. Each scope resolves its own variant independently, so the same DynamicResource key can return different values depending on which scope it appears in:

<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="CardBrush">White</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="CardBrush">#1E1E1E</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Window.Resources>
<ThemeVariantScope RequestedThemeVariant="Light">
<!-- Uses White -->
<Border Background="{DynamicResource CardBrush}" />
</ThemeVariantScope>

<ThemeVariantScope RequestedThemeVariant="Dark">
<!-- Uses #1E1E1E -->
<Border Background="{DynamicResource CardBrush}" />
</ThemeVariantScope>

Setting the variant from code​

You can change the variant at runtime by setting RequestedThemeVariant in your code-behind:

myScope.RequestedThemeVariant = ThemeVariant.Dark;

You can also bind the property to a view model so that your users can toggle themes dynamically:

<ThemeVariantScope RequestedThemeVariant="{Binding SelectedTheme}">
<ContentControl Content="{Binding CurrentPage}" />
</ThemeVariantScope>
public class MainViewModel : ViewModelBase
{
private ThemeVariant _selectedTheme = ThemeVariant.Default;

public ThemeVariant SelectedTheme
{
get => _selectedTheme;
set => this.RaiseAndSetIfChanged(ref _selectedTheme, value);
}
}

See also​