
Maui Theming
- 43 installs
- 163 repo stars
- Updated July 6, 2026
- davidortinau/maui-skills
Themes .NET MAUI apps with light/dark mode support via AppThemeBinding, dynamic resources, ResourceDictionary switching, and system theme detection.
About
Guides theming .NET MAUI apps with light/dark mode support via AppThemeBinding, dynamic resources, ResourceDictionary theme switching and system theme detection. A developer uses it when adding dark mode and dynamic theming to a MAUI app.
- Light/dark mode via AppThemeBinding and dynamic resources
- ResourceDictionary theme switching and system theme detection
Maui Theming by the numbers
- 43 all-time installs (skills.sh)
- Ranked #616 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davidortinau/maui-skills --skill maui-themingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 43 |
|---|---|
| repo stars | ★ 163 |
| Last updated | July 6, 2026 |
| Repository | davidortinau/maui-skills ↗ |
What it does
Themes .NET MAUI apps with light/dark mode support via AppThemeBinding, dynamic resources, ResourceDictionary switching, and system theme detection.
Files
.NET MAUI Theming
Choosing your approach
| Approach | Best for | Limitation |
|---|---|---|
| AppThemeBinding | Auto light/dark with OS — minimal code | Only two themes (light + dark) |
| ResourceDictionary swap | Custom branded themes, >2 themes, user preference | More setup, must use DynamicResource everywhere |
| Both combined | Auto OS response + custom theme colors | Most flexible but most complex |
Critical gotchas
Android: ConfigChanges.UiMode is REQUIRED
MainActivity must include ConfigChanges.UiMode or theme change events will not fire and the activity restarts instead of handling the change:
[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 { }Without UiMode, toggling dark mode in Android settings causes a full activity restart — losing navigation state and appearing as a crash to users.
CSS themes cannot be swapped at runtime
MAUI supports CSS styling, but CSS-based themes cannot be swapped dynamically. Use ResourceDictionary theming for runtime switching.
DynamicResource vs StaticResource
When using ResourceDictionary theme switching, you must use DynamicResource:
<!-- ✅ Updates when theme dictionary changes -->
<Label TextColor="{DynamicResource PrimaryTextColor}" />
<!-- ❌ Frozen at first load — won't update on theme switch -->
<Label TextColor="{StaticResource PrimaryTextColor}" />Quick reference
- OS light/dark →
AppThemeBindingmarkup extension - Theme colors in C# →
SetAppThemeColor(),SetAppTheme<T>() - Read OS theme →
Application.Current.RequestedTheme - Force theme →
Application.Current.UserAppTheme = AppTheme.Dark - Theme changes →
RequestedThemeChangedevent - Custom switching → Swap
ResourceDictionaryinMergedDictionaries - Runtime bindings → `DynamicResource` (not
StaticResource)
Theming API Reference
AppThemeBinding Markup Extension
Selects a value based on the current system theme.
| Property | Description |
|---|---|
Light | Value used when the device is in light mode |
Dark | Value used when the device is in dark mode |
Default | Fallback value when the device theme is unknown |
XAML Usage
<Label Text="Themed text"
TextColor="{AppThemeBinding Light=Green, Dark=Red}"
BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" />
<!-- With StaticResource or DynamicResource values -->
<Label TextColor="{AppThemeBinding Light={StaticResource LightPrimary},
Dark={StaticResource DarkPrimary}}" />C# Extension Methods
var label = new Label();
// Color-specific helper
label.SetAppThemeColor(Label.TextColorProperty, Colors.Green, Colors.Red);
// Generic helper for any type
label.SetAppTheme<Color>(Label.TextColorProperty, Colors.Green, Colors.Red);ResourceDictionary Theming (Custom Themes)
Use separate ResourceDictionary files with matching keys to define themes, then swap them at runtime.
Define Theme Dictionaries
Each ResourceDictionary must have a code-behind file that calls InitializeComponent().
LightTheme.xaml
<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>LightTheme.xaml.cs
namespace MyApp.Themes;
public partial class LightTheme : ResourceDictionary
{
public LightTheme() => InitializeComponent();
}DarkTheme.xaml.cs — same pattern, different values, same keys.
Consume with DynamicResource
Use DynamicResource (not StaticResource) so values update at runtime when the dictionary changes:
<ContentPage BackgroundColor="{DynamicResource PageBackgroundColor}">
<Label Text="Hello"
TextColor="{DynamicResource PrimaryTextColor}" />
<Button Text="Action"
BackgroundColor="{DynamicResource AccentColor}" />
</ContentPage>Switch Themes at Runtime
void ApplyTheme(ResourceDictionary theme)
{
var mergedDictionaries = Application.Current!.Resources.MergedDictionaries;
mergedDictionaries.Clear();
mergedDictionaries.Add(theme);
}
// Usage
ApplyTheme(new LightTheme());
ApplyTheme(new DarkTheme());System Theme Detection
Current Theme
AppTheme currentTheme = Application.Current!.RequestedTheme;
// Returns AppTheme.Light, AppTheme.Dark, or AppTheme.UnspecifiedOverride the System Theme
// Force a specific theme regardless of OS setting
Application.Current!.UserAppTheme = AppTheme.Dark;
// Reset to follow the system theme
Application.Current!.UserAppTheme = AppTheme.Unspecified;React to Theme Changes
Application.Current!.RequestedThemeChanged += (s, e) =>
{
AppTheme newTheme = e.RequestedTheme;
// Update UI or switch ResourceDictionaries
};Combining Both Approaches
Use AppThemeBinding with DynamicResource values for maximum flexibility:
<Label TextColor="{AppThemeBinding
Light={DynamicResource LightPrimary},
Dark={DynamicResource DarkPrimary}}" />Or react to system changes and swap full ResourceDictionaries:
Application.Current!.RequestedThemeChanged += (s, e) =>
{
ApplyTheme(e.RequestedTheme == AppTheme.Dark
? new DarkTheme()
: new LightTheme());
};Platform Support
| Platform | Minimum Version |
|---|---|
| iOS | 13+ |
| Android | 10+ (API 29) |
| macOS Catalyst | 10.14+ |
| Windows | 10+ |