Loading...
Loading...
Guide for theming .NET MAUI apps — light/dark mode via AppThemeBinding, ResourceDictionary theme switching, DynamicResource bindings, system theme detection, and user theme preferences. Use when: "dark mode", "light mode", "theming", "AppThemeBinding", "theme switching", "ResourceDictionary theme", "dynamic resources", "system theme detection", "color scheme", "app theme", "DynamicResource". Do not use for: localization or language switching (see .NET MAUI localization documentation), accessibility visual adjustments (see .NET MAUI accessibility documentation), app icons or splash screens (see .NET MAUI app icons documentation), or Bootstrap-style class theming (see Plugin.Maui.BootstrapTheme NuGet package).
npx skill4agent add dotnet/skills maui-themingPlugin.Maui.BootstrapThemeAppThemeBindingResourceDictionaryDynamicResourceAppThemeBindingApplication.Current.RequestedThemeRequestedThemeChangedPreferences.SetPreferences.GetConfigChanges.UiModeMainActivity| Approach | Best for | Limitation |
|---|---|---|
| AppThemeBinding | Automatic light/dark with OS — minimal code | Only two themes (light + dark) |
| ResourceDictionary swap | Custom branded themes, more than two themes, user preference | More setup; must use |
| Both combined | OS-driven response plus custom theme colors | Most flexible but most complex |
AppThemeBindingLightDarkDefault<Label Text="Themed text"
TextColor="{AppThemeBinding Light=Green, Dark=Red}"
BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" />
<!-- With resource references -->
<Label TextColor="{AppThemeBinding Light={StaticResource LightPrimary},
Dark={StaticResource DarkPrimary}}" />var label = new Label();
// Color-specific helper
label.SetAppThemeColor(Label.TextColorProperty, Colors.Green, Colors.Red);
// Generic helper for any bindable property type
label.SetAppTheme<Color>(Label.TextColorProperty, Colors.Green, Colors.Red);ResourceDictionaryx:ClassInitializeComponent()Sourcex:Class<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Themes.LightTheme">
<Color x:Key="PageBackgroundColor">White</Color>
<Color x:Key="PrimaryTextColor">#333333</Color>
<Color x:Key="AccentColor">#2196F3</Color>
</ResourceDictionary>namespace MyApp.Themes;
public partial class LightTheme : ResourceDictionary
{
public LightTheme() => InitializeComponent();
}DynamicResource<ContentPage BackgroundColor="{DynamicResource PageBackgroundColor}">
<Label Text="Hello"
TextColor="{DynamicResource PrimaryTextColor}" />
<Button Text="Action"
BackgroundColor="{DynamicResource AccentColor}" />
</ContentPage>void ApplyTheme(ResourceDictionary theme)
{
// Assumes theme dictionaries are the only merged dictionaries.
// If your App.xaml merges non-theme dictionaries (e.g., converters),
// move them to Application.Resources directly instead.
var mergedDictionaries = Application.Current!.Resources.MergedDictionaries;
mergedDictionaries.Clear();
mergedDictionaries.Add(theme);
}
// Usage
ApplyTheme(new DarkTheme());AppTheme currentTheme = Application.Current!.RequestedTheme;
// Returns AppTheme.Light, AppTheme.Dark, or AppTheme.Unspecified// Force dark mode regardless of OS setting
Application.Current!.UserAppTheme = AppTheme.Dark;
// Reset to follow system theme
Application.Current!.UserAppTheme = AppTheme.Unspecified;Application.Current!.RequestedThemeChanged += (s, e) =>
{
AppTheme newTheme = e.RequestedTheme;
// Update UI or switch ResourceDictionaries
};AppThemeBindingDynamicResource<Label TextColor="{AppThemeBinding
Light={DynamicResource LightPrimary},
Dark={DynamicResource DarkPrimary}}" />Application.Current!.RequestedThemeChanged += (s, e) =>
{
ApplyTheme(e.RequestedTheme == AppTheme.Dark
? new DarkTheme()
: new LightTheme());
};Preferences// Save choice
Preferences.Set("AppTheme", "Dark");
// Restore on startup (in App constructor or CreateWindow)
var saved = Preferences.Get("AppTheme", "System");
Application.Current!.UserAppTheme = saved switch
{
"Light" => AppTheme.Light,
"Dark" => AppTheme.Dark,
_ => AppTheme.Unspecified
};MainActivityConfigChanges.UiMode[Activity(Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize
| ConfigChanges.Orientation
| ConfigChanges.UiMode // ← Required for theme detection
| ConfigChanges.ScreenLayout
| ConfigChanges.SmallestScreenSize
| ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity { }UiModeDynamicResource<!-- ✅ Updates when theme dictionary changes -->
<Label TextColor="{DynamicResource PrimaryTextColor}" />
<!-- ❌ Frozen at first load — won't update on theme switch -->
<Label TextColor="{StaticResource PrimaryTextColor}" /><!-- ❌ Will not change with theme -->
<Label TextColor="#333333" />
<!-- ✅ Theme-aware -->
<Label TextColor="{DynamicResource PrimaryTextColor}" />x:Key| Platform | Minimum Version |
|---|---|
| iOS | 13+ |
| Android | 10+ (API 29) |
| macOS Catalyst | 10.15+ |
| Windows | 10+ |
AppThemeBindingSetAppThemeColor()SetAppTheme<T>()Application.Current.RequestedThemeApplication.Current.UserAppTheme = AppTheme.DarkRequestedThemeChangedResourceDictionaryMergedDictionariesDynamicResourceStaticResourcePreferences.SetPreferences.Get