.NET MAUI Platform Specific Styling Light,Dark Theme Step by step Implementation and Top 10 Questions and Answers
 Last Update: April 01, 2025      18 mins read      Difficulty-Level: beginner

.NET MAUI Platform-Specific Styling for Light and Dark Themes

When developing applications using .NET Multi-platform App UI (MAUI), handling light and dark themes is crucial to ensure your app provides a consistent and aesthetically pleasing user experience across iOS, Android, Windows, and macOS. This guide will explore in detail how to implement platform-specific styling for light and dark themes in .NET MAUI, covering important information to consider throughout the process.

Overview of .NET MAUI Theming

.NET MAUI supports theming through styles and resources, which are used to define the appearance of controls in an application. A theme in MAUI is essentially a collection of styles that can be applied dynamically based on the current user preference or system theme settings.

In .NET MAUI, themes include:

  • Light Theme: Typically used during the day, with a light background and dark text.
  • Dark Theme: Preferred in low-light conditions, featuring a dark background and light text.

Understanding the distinction between these themes is key to creating a visually coherent and accessible application.

Implementing Light and Dark Themes in .NET MAUI

1. Define Resource Dictionaries for Themes

The first step in implementing themes is to create separate resource dictionaries for light and dark themes. This organization helps in managing and maintaining the theme-specific styles efficiently.

Light Theme Resource Dictionary (LightTheme.xaml):

<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="YourNamespace.LightTheme">
    <Color x:Key="BackgroundColor">#FFFFFF</Color>
    <Color x:Key="TextColor">#000000</Color>
    <!-- Additional light theme styles here -->
</ResourceDictionary>

Dark Theme Resource Dictionary (DarkTheme.xaml):

<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="YourNamespace.DarkTheme">
    <Color x:Key="BackgroundColor">#000000</Color>
    <Color x:Key="TextColor">#FFFFFF</Color>
    <!-- Additional dark theme styles here -->
</ResourceDictionary>
2. Load the Appropriate Theme Based on System Settings

To ensure your application dynamically adapts to the user's system theme preferences, you should load the appropriate theme at runtime. This can be achieved by using the RequestedThemeChanged event for platform-specific handlers or by checking the system theme at startup.

In App.xaml, define placeholders for your themes:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary x:Name="CurrentThemeDictionary" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

In App.xaml.cs, load the initial theme:

public App()
{
    InitializeComponent();

    LoadAppTheme();

    // Subscribe to theme changes if required
    Microsoft.Maui.Controls.Application.Current.RequestedThemeChanged += OnAppThemeChanged;
}

private void LoadAppTheme()
{
    var requestedTheme = Microsoft.Maui.Controls.Application.Current.RequestedTheme;
    ApplyTheme(requestedTheme);
}

private void ApplyTheme(OSAppTheme theme)
{
    if (theme == OSAppTheme.Dark)
    {
        CurrentThemeDictionary.MergedDictionaries.Clear();
        CurrentThemeDictionary.MergedDictionaries.Add(new DarkTheme());
    }
    else
    {
        CurrentThemeDictionary.MergedDictionaries.Clear();
        CurrentThemeDictionary.MergedDictionaries.Add(new LightTheme());
    }
}

private void OnAppThemeChanged(object sender, AppThemeChangedEventArgs e)
{
    ApplyTheme(e.RequestedTheme);
}
3. Platform-Specific Customization

While the above steps cover the core aspects of theming, you might need to incorporate platform-specific styling or behavior. Here are some ways to handle platform-specific needs:

  • Platform-Specific Styles: If certain styles differ significantly between platforms, it's best to define them within separate resource dictionaries and include them accordingly.
if (Device.RuntimePlatform == Device.iOS)
{
    CurrentThemeDictionary.MergedDictionaries.Add(new iOSLightTheme());
}
else if (Device.RuntimePlatform == Device.Android)
{
    CurrentThemeDictionary.MergedDictionaries.Add(new AndroidLightTheme());
}
  • Conditional Compilation: Use conditional compilation if certain code paths must be platform-specific.
#if ANDROID
// Android-specific theme logic
#elif iOS
// iOS-specific theme logic
#endif

Important Considerations

  1. Accessibility: Ensure that your application remains accessible in all themes by selecting appropriate color contrasts. Tools like the Color Contrast Analyzer can help verify accessibility compliance.

  2. Testing: Thoroughly test your application across different devices and orientations to ensure that themes are applied correctly and do not introduce any visual glitches or performance issues.

  3. Performance: Be mindful of the performance impact of dynamically switching themes. Efficiently managing resources and minimizing recomputation will help maintain smooth app performance.

  4. User Preference: Allow users to override the system theme if they have a preference for a specific theme. Providing an option to switch themes from within the app settings enhances user satisfaction.

  5. Platform-Specific Behaviors: Certain behaviors might require platform-specific implementations. For example, handling specific gestures or system dialogs should be addressed in the context of the target platform.

  6. Fallback Themes: Define fallback themes for scenarios where the system theme cannot be determined. This prevents the application from displaying an unstyled or incorrect theme.

Conclusion

Implementing platform-specific styling for light and dark themes in .NET MAUI involves defining distinct resource dictionaries, dynamically loading the appropriate theme based on user preferences, and addressing platform-specific nuances. By following best practices and considering the factors outlined above, you can create a visually appealing and highly adaptable application that delivers an excellent user experience across multiple platforms.

By adhering to these guidelines, developers can harness the full power of .NET MAUI to create visually compelling applications that respect user preferences and cater to diverse environments.

Step-by-Step Guide to Implementing Platform-Specific Styling with Light and Dark Themes in .NET MAUI

Welcome to this comprehensive guide that will help you understand how to implement platform-specific styling that includes light and dark themes in .NET Multi-platform App UI (.NET MAUI). We will walk you through the process from setting up your application to running it and ensuring the data flows seamlessly. This step-by-step guide is designed for beginners, focusing on clarity and ease of understanding.


Step 1: Setting Up Your .NET MAUI Project

  1. Install .NET MAUI SDK: Before you start, make sure you have the latest .NET MAUI SDK installed on your machine. You can download it from the .NET MAUI official page.

  2. Create a New Project: Open Visual Studio or .NET CLI and create a new .NET MAUI project. In Visual Studio, go to File -> New -> Project, then select MAUI App (Preview). In the CLI, use the following command:

    dotnet new maui -n MyApp
    cd MyApp
    
  3. Open the Project: Once the project is created, open it in your preferred IDE. You will see a default project structure with platforms, shared code, and resources.


Step 2: Defining Resource Dictionaries for Themes

  1. Create Resource Dictionaries: In your project, create two new resource dictionaries: one for the light theme (LightTheme.xaml) and another for the dark theme (DarkTheme.xaml). You can do this by right-clicking on your project in Solution Explorer and selecting Add -> New Item -> Resource Dictionary (XAML).

  2. Define Styles in LightTheme.xaml: In LightTheme.xaml, define styles for controls that are appropriate for a light theme, such as button colors, text colors, background colors, and more.

    <!-- LightTheme.xaml -->
    <ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        x:Class="MyApp.LightTheme">
      <Style TargetType="Button">
        <Setter Property="BackgroundColor" Value="#FFF" />
        <Setter Property="TextColor" Value="#000" />
        <Setter Property="BorderColor" Value="#CCC" />
      </Style>
      <Style TargetType="Label">
        <Setter Property="TextColor" Value="#000" />
      </Style>
    </ResourceDictionary>
    
  3. Define Styles in DarkTheme.xaml: Similarly, in DarkTheme.xaml, define styles for controls appropriate for a dark theme.

    <!-- DarkTheme.xaml -->
    <ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        x:Class="MyApp.DarkTheme">
      <Style TargetType="Button">
        <Setter Property="BackgroundColor" Value="#333" />
        <Setter Property="TextColor" Value="#FFF" />
        <Setter Property="BorderColor" Value="#666" />
      </Style>
      <Style TargetType="Label">
        <Setter Property="TextColor" Value="#FFF" />
      </Style>
    </ResourceDictionary>
    

Step 3: Switching Between Themes

  1. Update App.xaml.cs: Modify your App.xaml.cs to include methods for switching themes and load the appropriate resource dictionaries.

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            RequestTheme();
            MainPage = new MainPage();
        }
    
        private void RequestTheme()
        {
            string theme = Preferences.Get("theme", "Light");
            LoadTheme(theme);
        }
    
        public void LoadTheme(string theme)
        {
            Resources.Clear();
            Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = theme == "Light" ? new Uri("Resource://MyApp.LightTheme.xaml", UriKind.Relative) 
                   : new Uri("Resource://MyApp.DarkTheme.xaml", UriKind.Relative)
            });
        }
    
        public void ToggleTheme()
        {
            string theme = Preferences.Get("theme", "Light") == "Light" ? "Dark" : "Light";
            Preferences.Set("theme", theme);
            LoadTheme(theme);
        }
    }
    
  2. Add a Toggle Button in MainPage.xaml: In MainPage.xaml, add a button to allow the user to toggle between themes.

    <!-- MainPage.xaml -->
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MyApp.MainPage">
      <StackLayout>
        <Button Text="Toggle Theme" Clicked="ToggleButton_Clicked" />
        <Label Text="Welcome to .NET MAUI Theme Example!" />
      </StackLayout>
    </ContentPage>
    
  3. Handle Button Click in MainPage.xaml.cs: In MainPage.xaml.cs, handle the button click event to toggle the theme.

    // MainPage.xaml.cs
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    
        private void ToggleButton_Clicked(object sender, EventArgs e)
        {
            ((App)Application.Current).ToggleTheme();
        }
    }
    

Step 4: Running the Application

  1. Build and Run: Build and run your application. When you click the "Toggle Theme" button, the theme should switch between light and dark based on the styles defined in your resource dictionaries.

    • In Visual Studio, you can run your application by pressing F5 or clicking the green play button.
    • In the CLI, you can use the following command:
      dotnet build
      dotnet maui run
      
  2. Platform-Specific Considerations: Make sure to test your application on different platforms to ensure the themes render correctly. .NET MAUI supports various platforms like iOS, Android, Windows, and macOS, so it’s essential to verify the experience across all of them.


Step 5: Data Flow and User Experience

  1. Maintain Data Consistency: Ensure that your application maintains data consistency when switching themes. This includes saving the user’s theme preference in Preferences or a local database and loading it when the application starts.

  2. Optimize Performance: Be mindful of the performance impact of dynamically changing themes. While .NET MAUI is efficient, loading resource dictionaries at runtime can have an impact, especially on mobile devices. Optimize your resource definitions and consider lazy loading if necessary.

  3. User Experience: Provide a smooth and intuitive user experience. Clearly indicate when the theme is being switched and consider adding animations or transitions to make the change more visually appealing.


Conclusion

Implementing platform-specific styling with light and dark themes in .NET MAUI is a powerful way to enhance user experience across different platforms. By following the steps outlined in this guide, you can create visually appealing and functional applications that adapt to the user's preferences. Remember to test thoroughly and optimize for performance to ensure a seamless user experience. Happy coding!

Top 10 Questions and Answers: .NET MAUI Platform-Specific Styling for Light and Dark Themes

1. What is .NET MAUI, and how does it support light and dark themes?

Answer:
.NET Multi-platform App UI (MAUI) is a framework that enables developers to build native user interface layouts that can run on multiple platforms, including Windows, macOS, iOS, and Android, using a single codebase. While .NET MAUI natively supports light and dark themes, platform-specific styling allows developers to customize how these themes appear on individual operating systems. Developers can use styles, resource dictionaries, and triggers to apply specific styling logic for different platforms, ensuring a consistent user experience across devices.

2. How can I define light and dark themes in a .NET MAUI application?

Answer:
Defining light and dark themes in .NET MAUI typically involves creating separate resource dictionaries for each theme. You can set the desired styles and colors within these dictionaries and then switch between them based on the user's system preferences or application settings.

Here’s an example of how to define these themes:

//LightTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.LightTheme">
    <Color x:Key="BackgroundColor">#FFFFFF</Color>
    <Color x:Key="TextColor">#000000</Color>
</ResourceDictionary>

//DarkTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.DarkTheme">
    <Color x:Key="BackgroundColor">#121212</Color>
    <Color x:Key="TextColor">#FFFFFF</Color>
</ResourceDictionary>

After creating these dictionaries, you can apply them to your application in your App.xaml file.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <!-- Default Light Theme -->
            <ResourceDictionary Include="LightTheme.xaml" x:Key="LightTheme"/>
            <ResourceDictionary Include="DarkTheme.xaml" x:Key="DarkTheme"/>
        </ResourceDictionary.MergedDictionaries>
        
        <!-- Switching Themes -->
        <Style TargetType="ContentPage">
            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource BackgroundColor}, Dark={StaticResource BackgroundColor}}"/>
            <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextColor}, Dark={StaticResource TextColor}}"/>
        </Style>
    </ResourceDictionary>
</Application.Resources>

3. How do I implement platform-specific styling for light and dark themes in .NET MAUI?

Answer:
Platform-specific styling in .NET MAUI can be achieved using OnPlatform and OnIdiom markup extensions. These extensions allow you to define different values for styles, properties, and resources based on the platform (e.g., iOS, Android) and idiom (e.g., phone, tablet). However, for theme-specific styling, it's more effective to use AppThemeBinding.

Here’s an example of platform-specific styling:

<Style TargetType="Button">
    <Setter Property="TextColor">
        <Setter.Value>
            <OnPlatform x:TypeArguments="Color">
                <On Platform="Android">#FF0000</On>
                <On Platform="iOS">#0000FF</On>
            </OnPlatform>
        </Setter.Value>
    </Setter>
</Style>

For theme-specific styling combined with platform-specific styles, you can use the AppThemeBinding extension to switch styles based on the current theme and then apply platform-specific styles within those themes.

4. How do I detect the user's system theme preference in .NET MAUI?

Answer:
.NET MAUI provides built-in support for detecting the system theme preference through the AppTheme class. You can subscribe to the AppTheme.Current.Changed event to handle changes in the system theme preference and update your application's theme accordingly.

Here’s an example:

public App()
{
    InitializeComponent();
    MainPage = new MainPage();

    // Subscribe to theme change event
    AppResourceProvider.CurrentCultureChanged += OnCultureChanged;
    AppTheme.Current.Changed += OnAppThemeChanged;
}

private void OnAppThemeChanged(object sender, EventArgs e)
{
    var currentTheme = AppTheme.Current.RequestedTheme;
    switch (currentTheme)
    {
        case OSAppTheme.Light:
            Current.Resources.MergedDictionaries[0] = new LightTheme();
            break;
        case OSAppTheme.Dark:
            Current.Resources.MergedDictionaries[0] = new DarkTheme();
            break;
        case OSAppTheme.Unspecified:
            // Handle unspecified theme if necessary
            break;
    }
}

5. Can I allow users to choose between light and dark themes within my .NET MAUI application?

Answer:
Absolutely! In addition to detecting and responding to the system theme preference, you can also provide an in-app option for users to manually switch between light and dark themes.

Here’s how you can implement this feature:

  1. Create ToggleSwitch for Theme Selection:
<ToggleSwitch IsToggled="{Binding IsDarkTheme, Mode=TwoWay}" Text="Dark Mode"/>
  1. Update Theme Based on ToggleSwitch State:
public class MainViewModel : INotifyPropertyChanged
{
    private bool _isDarkTheme;
    public bool IsDarkTheme
    {
        get => _isDarkTheme;
        set
        {
            _isDarkTheme = value;
            OnPropertyChanged(nameof(IsDarkTheme));
            App.Current.UserAppTheme = _isDarkTheme ? OSAppTheme.Dark : OSAppTheme.Light;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

6. How do I handle different font sizes for various themes in .NET MAUI?

Answer:
You can define different font sizes for each theme by creating separate resource dictionaries and using AppThemeBinding to apply the appropriate font size based on the current theme.

Here’s an example:

//LightTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.LightTheme">
    <x:Double x:Key="FontSize">14</x:Double>
</ResourceDictionary>

//DarkTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.DarkTheme">
    <x:Double x:Key="FontSize">16</x:Double>
</ResourceDictionary>

Then, apply these font sizes to your UI elements using AppThemeBinding:

<Label Text="Hello, World!"
       FontSize="{AppThemeBinding Light={StaticResource FontSize}, Dark={StaticResource FontSize}}"/>

7. What are some best practices for managing light and dark themes in .NET MAUI applications?

Answer:
Here are some best practices for effectively managing light and dark themes in .NET MAUI:

  • Use Resource Dictionaries: Define your themes in separate resource dictionaries to maintain clean and organized code.
  • Leverage AppThemeBinding: Use AppThemeBinding for properties that need to change based on the current theme.
  • Avoid Hardcoding Colors: Use resources to define colors, fonts, and other style attributes, making it easier to switch themes.
  • Stay Consistent: Ensure that all controls and UI elements adjust consistently across themes to provide a cohesive user experience.
  • Test on All Platforms: Verify that your themes render correctly on all target platforms and adjust styling as necessary.

8. How can I dynamically change themes without restarting the application in .NET MAUI?

Answer:
You can dynamically change themes without restarting the application by updating the resource dictionaries at runtime. Here’s an example:

  1. Create Methods to Set Themes:
public void SetLightTheme()
{
    var lightTheme = new LightTheme();
    var mergedDictionaries = Current.Resources.MergedDictionaries;
    if (mergedDictionaries.Any())
    {
        mergedDictionaries[0] = lightTheme;
    }
    else
    {
        mergedDictionaries.Add(lightTheme);
    }
}

public void SetDarkTheme()
{
    var darkTheme = new DarkTheme();
    var mergedDictionaries = Current.Resources.MergedDictionaries;
    if (mergedDictionaries.Any())
    {
        mergedDictionaries[0] = darkTheme;
    }
    else
    {
        mergedDictionaries.Add(darkTheme);
    }
}
  1. Bind ToggleSwitch to Theme Change Method:
<ToggleSwitch IsToggled="{Binding IsDarkTheme, Mode=TwoWay}" Toggled="OnDarkThemeToggled"/>
  1. Handle Toggled Event:
private void OnDarkThemeToggled(object sender, ToggledEventArgs e)
{
    var app = Application.Current as App;
    if (e.Value)
    {
        app.SetDarkTheme();
    }
    else
    {
        app.SetLightTheme();
    }
}

9. Is it possible to customize icons and images based on light and dark themes in .NET MAUI?

Answer:
Yes, you can customize icons and images based on the current theme in .NET MAUI. You can define separate resource dictionaries for light and dark themes, specifying different images for each theme.

Here’s an example:

  1. Create Resource Dictionaries for Icons:
//LightTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.LightTheme">
    <x:String x:Key="IconPath">light_icon.png</x:String>
</ResourceDictionary>

//DarkTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="MyApp.DarkTheme">
    <x:String x:Key="IconPath">dark_icon.png</x:String>
</ResourceDictionary>
  1. Bind Icons in XAML:
<Image Source="{AppThemeBinding Light={StaticResource IconPath}, Dark={StaticResource IconPath}}"/>

10. What are some common pitfalls to avoid when implementing light and dark themes in .NET MAUI applications?

Answer:
Here are some common pitfalls to avoid when implementing light and dark themes in .NET MAUI:

  • Hardcoding Colors: Avoid hardcoding colors directly in your XAML or code. This can make it difficult to switch themes and can lead to inconsistent styling.
  • Ignoring Platform Differences: Each platform may have its own conventions and color schemes for themes. Make sure to test your themes on each platform and adjust them accordingly.
  • Not Testing Thoroughly: It’s important to test your application with both light and dark themes across all pages and components to ensure a consistent user experience.
  • Overusing Platform-Specific Styles: While platform-specific styles can be useful, overusing them can lead to code that is difficult to maintain and may compromise cross-platform consistency.
  • Forgetting to Update Resources: Ensure that all resources (colors, fonts, images) are updated in both light and dark themes. This includes background colors, text colors, icon images, and any other style attributes.

By following these best practices and avoiding common pitfalls, you can create effective and visually appealing light and dark themes in your .NET MAUI applications.