MAUI - Apply style at runtime

How to Dynamically Change Styles in a MAUI Application

In this article, I will demonstrate how to dynamically change the style of a MAUI application at runtime.

You can find the source code on  my GitHub.

To add or modify styles, you can work with Application.Current.Resources.MergedDictionaries

The principle is to remove a resource and add another one with the new values. An example might be the following:

Application.Current.Resources.MergedDictionaries.Remove(themeToDelete);
Application.Current.Resources.MergedDictionaries.Add(themeToAdd);

I suppose you already have some questions in your mind:

  1. Will the binding of the new values be applied immediately?
  2. How can I determine which "ResourceDictionary" to remove?

Let's start with the first question

Yes, but it requires taking a few precautions to ensure the new values are correctly applied.

First of all, you need to create at least one 'Theme', which means adding a XAML file of the appropriate type along with its corresponding C# code.

Theme1.xaml
<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="MauiApplyStyleAtRuntime.Resources.Styles.Themes.Theme1"
    >

    <Color x:Key="Primary">#512BD4</Color>
    <Color x:Key="PrimaryDark">#ac99ea</Color>
</ResourceDictionary>
C#
public partial class Theme1
{
    public Theme1()
    {
        InitializeComponent();
    }
}

Furthermore, the binding must be done using DynamicResource instead of StaticResource."
"Below is line 28 from the Styles.xaml file:

<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={DynamicResource Primary}, Dark={DynamicResource PrimaryDark}}" />

How can I determine which ResourceDictionary to remove?

To know which theme to remove, I created a base class ThemeBase and modified the themes as follows:

Theme1.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<th:ThemeBase 
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="MauiApplyStyleAtRuntime.Resources.Styles.Themes.Theme1"
    
    xmlns:th="clr-namespace:MauiApplyStyleAtRuntime.Resources.Styles.Themes" 
    >

    <Color x:Key="Primary">#512BD4</Color>
    <Color x:Key="PrimaryDark">#ac99ea</Color>
</th:ThemeBase>
Theme1.xaml.cs
namespace MauiApplyStyleAtRuntime.Resources.Styles.Themes
{
    public partial class Theme1: ThemeBase
    {
        public Theme1()
        {
            InitializeComponent();
        }
    }    
}

The theme is changed in the MainPageViewModel using the following method, which removes all ThemeBase resources and adds the new one:

MainPageViewModel.cs
public MainPageViewModel()
{
    SetTheme1 = new Command(() => {
        SetTheme(new Theme1());
    });

    SetTheme2 = new Command(() => {
        SetTheme(new Theme2());
    });

    SetTheme3 = new Command(() => {
        SetTheme(new Theme3());
    });

    SetTheme4 = new Command(() => {
        SetTheme(new Theme4());
    });
}

private void SetTheme(ThemeBase theme)
{
    var mergedDictionaries = Application.Current.Resources.MergedDictionaries.ToList<ResourceDictionary>();

    var themesToDelete = mergedDictionaries.Where(x => x.GetType() == typeof(ThemeBase)).ToList();

    foreach (var themeToDelete in themesToDelete)
    {
        Application.Current.Resources.MergedDictionaries.Remove(themeToDelete);
    }

    Application.Current.Resources.MergedDictionaries.Add(theme);
}

Feel free to leave a comment or connect with me on Linkedin for further discussions on MAUI and other .NET technologies!