MAUI - Apply style at runtime
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:
- Will the binding of the new values be applied immediately?
- 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.
<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>
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:
<?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>
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:
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!