$npx -y skills add managedcode/dotnet-skills --skill maui-themingGuide 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", "Resourc
| 1 | # .NET MAUI Theming |
| 2 | |
| 3 | Apply light/dark mode support, custom branded themes, and runtime theme switching in .NET MAUI apps using AppThemeBinding, ResourceDictionary swapping, and system theme detection APIs. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - Adding light and dark mode support to a .NET MAUI app |
| 8 | - Creating custom branded themes with ResourceDictionary |
| 9 | - Detecting and responding to system theme changes at runtime |
| 10 | - Letting users choose a preferred theme (light, dark, or system default) |
| 11 | - Combining OS-driven theme response with custom color palettes |
| 12 | |
| 13 | ## When Not to Use |
| 14 | |
| 15 | - Localization or language switching — see [.NET MAUI localization docs](https://learn.microsoft.com/dotnet/maui/fundamentals/localization) |
| 16 | - Accessibility-specific visual adjustments — see [.NET MAUI accessibility docs](https://learn.microsoft.com/dotnet/maui/fundamentals/accessibility) |
| 17 | - App icon or splash screen configuration — see [.NET MAUI app icon docs](https://learn.microsoft.com/dotnet/maui/user-interface/images/app-icons) |
| 18 | - Bootstrap-style class theming — see the `Plugin.Maui.BootstrapTheme` NuGet package |
| 19 | |
| 20 | ## Inputs |
| 21 | |
| 22 | - A .NET MAUI project targeting .NET 8 or later |
| 23 | - XAML pages or C# UI code that need theme-aware styling |
| 24 | |
| 25 | ## Workflow |
| 26 | |
| 27 | 1. Detect the current theme approach in the project (AppThemeBinding, ResourceDictionary, or none). |
| 28 | 2. Choose the appropriate strategy: AppThemeBinding for simple light/dark, ResourceDictionary swap for custom/multiple themes, or both combined. |
| 29 | 3. Define theme resources — inline `AppThemeBinding` values or separate `ResourceDictionary` files with matching keys. |
| 30 | 4. Replace hardcoded colors with `DynamicResource` bindings (or `AppThemeBinding` markup) throughout XAML pages. |
| 31 | 5. Add system theme detection via `Application.Current.RequestedTheme` and the `RequestedThemeChanged` event. |
| 32 | 6. Implement user preference persistence with `Preferences.Set` / `Preferences.Get` and apply on startup. |
| 33 | 7. Verify Android `ConfigChanges.UiMode` is set on `MainActivity` to avoid activity restarts on theme change. |
| 34 | 8. Test both light and dark themes on at least one target platform, confirming all UI elements respond correctly. |
| 35 | |
| 36 | ## Choosing an Approach |
| 37 | |
| 38 | | Approach | Best for | Limitation | |
| 39 | |----------|----------|------------| |
| 40 | | **AppThemeBinding** | Automatic light/dark with OS — minimal code | Only two themes (light + dark) | |
| 41 | | **ResourceDictionary swap** | Custom branded themes, more than two themes, user preference | More setup; must use `DynamicResource` everywhere | |
| 42 | | **Both combined** | OS-driven response plus custom theme colors | Most flexible but most complex | |
| 43 | |
| 44 | ## AppThemeBinding (OS Light/Dark) |
| 45 | |
| 46 | `AppThemeBinding` selects a value based on the current system theme. It supports `Light`, `Dark`, and an optional `Default` fallback. |
| 47 | |
| 48 | ### XAML |
| 49 | |
| 50 | ```xml |
| 51 | <Label Text="Themed text" |
| 52 | TextColor="{AppThemeBinding Light=Green, Dark=Red}" |
| 53 | BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" /> |
| 54 | |
| 55 | <!-- With resource references --> |
| 56 | <Label TextColor="{AppThemeBinding Light={StaticResource LightPrimary}, |
| 57 | Dark={StaticResource DarkPrimary}}" /> |
| 58 | ``` |
| 59 | |
| 60 | ### C# Extension Methods |
| 61 | |
| 62 | ```csharp |
| 63 | var label = new Label(); |
| 64 | |
| 65 | // Color-specific helper |
| 66 | label.SetAppThemeColor(Label.TextColorProperty, Colors.Green, Colors.Red); |
| 67 | |
| 68 | // Generic helper for any bindable property type |
| 69 | label.SetAppTheme<Color>(Label.TextColorProperty, Colors.Green, Colors.Red); |
| 70 | ``` |
| 71 | |
| 72 | ## ResourceDictionary Theming (Custom Themes) |
| 73 | |
| 74 | Use separate `ResourceDictionary` files with matching keys to define themes, then swap them at runtime. |
| 75 | |
| 76 | ### Step 1 — Define Theme Dictionaries |
| 77 | |
| 78 | When using compiled XAML with `x:Class` (as shown below), each dictionary needs a code-behind that calls `InitializeComponent()`. Dictionaries loaded via `Source` without `x:Class` do not need code-behind. |
| 79 | |
| 80 | **LightTheme.xaml** |
| 81 | |
| 82 | ```xml |
| 83 | <ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
| 84 | xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
| 85 | x:Class="MyApp.Themes.LightTheme"> |
| 86 | <Color x:Key="PageBackgroundColor">White</Color> |
| 87 | <Color x:Key="PrimaryTextColor">#333333</Color> |
| 88 | <Color x:Key="AccentColor">#2196F3</Color> |
| 89 | </ResourceDictionar |