Learn how to use resource dictionaries to reuse styles and other data across your .NET MAUI-based application.
Throughout this post, you’ll learn what resource dictionaries are and how you can use them to reuse styles and other data across your .NET MAUI-based application. Let’s get started!
The first thing you should know is that a resource dictionary is a repository of resources used by a .NET MAUI application that can contain practically any type of resource. Some of the most common resources stored in these dictionaries are:
Regarding resource dictionaries, you should know that any element that derives from VisualElement
(pages, layouts and controls) as well as the Application
class contain a Resources
property of type ResourceDictionary
. It is in this property that we can store the resources we’ll use in the application.
The main advantage of using resource dictionaries is that we can centralize resources that we need to reuse constantly. For example, you might have UI requirements to have a margin for the main container of all pages in your application, defined font sizes, styles for Entry
controls, collections, etc. You can even define design themes that completely change the look and feel of your application!
For example, instead of having controls with lots of assigned properties like the following:
<VerticalStackLayout Padding="30,0" Spacing="25">
<Button
BackgroundColor="DarkBlue"
FontAttributes="Bold"
FontSize="16"
HeightRequest="100"
HorizontalOptions="Center"
Text="Hello world!"
TextColor="White"
WidthRequest="200" />
<Button
BackgroundColor="DarkBlue"
FontAttributes="Bold"
FontSize="16"
HeightRequest="100"
HorizontalOptions="Center"
Text="Hello world!"
TextColor="White"
WidthRequest="200" />
</VerticalStackLayout>
You can have simplified code that looks like this:
<ContentPage.Resources>
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="DarkBlue" />
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="FontSize" Value="16" />
<Setter Property="HeightRequest" Value="100" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="TextColor" Value="White" />
<Setter Property="WidthRequest" Value="200" />
</Style>
</ContentPage.Resources>
<ScrollView>
<VerticalStackLayout Padding="30,0" Spacing="25">
<Button Text="Click Me!" />
<Button Text="Perform action!" />
</VerticalStackLayout>
</ScrollView>
This undoubtedly makes the code cleaner and more readable. Let’s see how to define these resource dictionaries.
A resource dictionary will always be defined within a control’s Resources
property. The complete way to define it is as follows:
<YourVisualElement.Resources>
<ResourceDictionary>
Resources
</ResourceDictionary>
</YourVisualElement.Resources>
You can also omit the use of the ResourceDictionary
tag, and simplify it as follows:
<YourVisualElement.Resources>
Resources
</YourVisualElement.Resources>
This means we can declare a resource dictionary directly within a control’s Resources
property. Let’s say we’re creating a design for a card using the RadBorder
control, adding the control properties in each control’s resource dictionary:
<Grid RowDefinitions="*,*">
<telerik:RadBorder x:Name="flatBorder" WidthRequest="350">
<telerik:RadBorder.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Thickness x:Key="Thickness">1</Thickness>
<CornerRadius x:Key="CornerRadius">0, 8, 8, 0</CornerRadius>
<Style TargetType="telerik:RadBorder">
<Setter Property="BorderColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{StaticResource Thickness}" />
<Setter Property="CornerRadius" Value="{StaticResource CornerRadius}" />
</Style>
</telerik:RadBorder.Resources>
<Grid RowDefinitions=".2*,.6*,.2*">
<Label Margin="8" Text=".NET MAUI Border Overview">
<Label.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Style TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
</Label.Resources>
</Label>
<Label
Grid.Row="1"
Margin="8"
Text="The Telerik UI for .NET MAUI Border enables you to control the look and feel of the border that wraps around your MAUI views. It provides various border thickness types and corner-side radiuses, which can be used for surrounding labels, images, and other elements.">
<Label.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Style TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
</Label.Resources>
</Label>
<Button Grid.Row="2" Text="Learn More">
<Button.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="TextColor" Value="White" />
<Setter Property="Margin" Value="10" />
</Style>
</Button.Resources>
</Button>
</Grid>
</telerik:RadBorder>
</Grid>
In the code above, you can see how each control has a resource dictionary that we’ve modified to add characteristics specific to each control, including Color
, Thickness
, CornerRadius
and Style
types.
In the case of the Style
tag, we see that the TargetType
property equals telerik:RadBorder
, which means this style will only affect controls of this type, applying the properties with their respective values declared in the Setter
tags.
When running the application with the above code, we get the following result:
It’s important to note that resources declared within a control will only be accessible by that specific control, which is why we’ve had to define the MainColor
resource within each of them, which is not practical at all.
In these cases, it’s better to define the resources in a VisualElement
with a higher hierarchy—for example, at the container Layout level as follows:
<Grid RowDefinitions="*,*">
<Grid.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Thickness x:Key="Thickness">1</Thickness>
<CornerRadius x:Key="CornerRadius">0, 8, 8, 0</CornerRadius>
<Style TargetType="telerik:RadBorder">
<Setter Property="BorderColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{StaticResource Thickness}" />
<Setter Property="CornerRadius" Value="{StaticResource CornerRadius}" />
</Style>
<Style TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="TextColor" Value="White" />
<Setter Property="Margin" Value="10" />
</Style>
</Grid.Resources>
<telerik:RadBorder x:Name="flatBorder" WidthRequest="350">
<Grid RowDefinitions=".2*,.6*,.2*">
<Label Margin="8" Text=".NET MAUI Border Overview" />
<Label
Grid.Row="1"
Margin="8"
Text="The Telerik UI for .NET MAUI Border enables you to control the look and feel of the border that wraps around your MAUI views. It provides various border thickness types and corner-side radiuses, which can be used for surrounding labels, images, and other elements." />
<Button Grid.Row="2" Text="Learn More" />
</Grid>
</telerik:RadBorder>
</Grid>
In the code above, we’ve extracted all resources from the controls to place them at the main Grid level, reusing MainColor
. Although the code looks correct in principle, it has the problem that there are two styles with a TargetType
equal to Label
:
<Style TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
This causes the compiler to not know which style to apply when it finds a Label
control in the code. Let’s see how to solve this problem.
When a style only has the TargetType
property pointing to a specific control type, it means that all controls will apply that style. It’s very likely that in a larger application you’ll want to have multiple styles pointing to the same control. We’ll achieve this by adding the x:Key
property to a style, which will allow us to reference it in a control.
Let’s start by adding the x:Key
property to the styles:
<Style TargetType="Label" x:Key="TitleStyle">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Label" x:Key="BodyStyle">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
Then, to apply a style to a control, you must use the Style
property, indicating the key of the style to use as follows:
<Label
Margin="8"
Style="{StaticResource TitleStyle}"
Text=".NET MAUI Border Overview" />
<Label
Grid.Row="1"
Margin="8"
Style="{StaticResource BodyStyle}"
Text="The Telerik UI for .NET MAUI Border enables you to control the look and feel of the border that wraps around your MAUI views. It provides various border thickness types and corner-side radiuses, which can be used for surrounding labels, images, and other elements." />
With this, although two styles point to the same Label
control type, an explicit assignment is made of which style will be used in each of them.
Another place where it’s also possible to store resources is at the ContentPage
level, which would result in a better place because we separate the Views section from the definition of resources as follows:
<ContentPage.Resources>
<Color x:Key="MainColor">#21004f</Color>
<Thickness x:Key="Thickness">1</Thickness>
<CornerRadius x:Key="CornerRadius">0, 8, 8, 0</CornerRadius>
<Style TargetType="telerik:RadBorder">
<Setter Property="BorderColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{StaticResource Thickness}" />
<Setter Property="CornerRadius" Value="{StaticResource CornerRadius}" />
</Style>
<Style x:Key="TitleStyle" TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style x:Key="BodyStyle" TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="TextColor" Value="White" />
<Setter Property="Margin" Value="10" />
</Style>
</ContentPage.Resources>
<Grid RowDefinitions="*,*">
<telerik:RadBorder x:Name="flatBorder" WidthRequest="350">
<Grid RowDefinitions=".2*,.6*,.2*">
<Label
Margin="8"
Style="{StaticResource TitleStyle}"
Text=".NET MAUI Border Overview" />
<Label
Grid.Row="1"
Margin="8"
Style="{StaticResource BodyStyle}"
Text="The Telerik UI for .NET MAUI Border enables you to control the look and feel of the border that wraps around your MAUI views. It provides various border thickness types and corner-side radiuses, which can be used for surrounding labels, images, and other elements." />
<Button Grid.Row="2" Text="Learn More" />
</Grid>
</telerik:RadBorder>
</Grid>
Now, in case you want to be able to reuse this resource across several ContentPage
s, you have a file in the root of your project called App.xaml
, which you can modify to add the resources section as follows:
<Application.Resources>
<ResourceDictionary>
<Color x:Key="MainColor">#21004f</Color>
<Thickness x:Key="Thickness">1</Thickness>
<CornerRadius x:Key="CornerRadius">0, 8, 8, 0</CornerRadius>
<Style TargetType="telerik:RadBorder">
<Setter Property="BorderColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{StaticResource Thickness}" />
<Setter Property="CornerRadius" Value="{StaticResource CornerRadius}" />
</Style>
<Style x:Key="TitleStyle" TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style x:Key="BodyStyle" TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="TextColor" Value="White" />
<Setter Property="Margin" Value="10" />
</Style>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Remember to add all control references so you don’t have problems with the code above. Now, although the above code works without problems, it makes the App.xaml
file look a bit messy, especially because the more styles you add to your application, the more XAML code you’ll have here.
What we can do is add a new file by right-clicking on the Resources
| Styles
folder, selecting the .NET MAUI
category and finally selecting the .NET MAUI ResourceDictionary (XAML)
template, as shown below:
In this new Resource Dictionary, we’ll add our styles code as follows:
<ResourceDictionary
x:Class="DictionariesDemo.Resources.Styles.MyStyles"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui">
<Color x:Key="MainColor">#21004f</Color>
<Thickness x:Key="Thickness">1</Thickness>
<CornerRadius x:Key="CornerRadius">0, 8, 8, 0</CornerRadius>
<Style TargetType="telerik:RadBorder">
<Setter Property="BorderColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{StaticResource Thickness}" />
<Setter Property="CornerRadius" Value="{StaticResource CornerRadius}" />
</Style>
<Style x:Key="TitleStyle" TargetType="Label">
<Setter Property="FontSize" Value="25" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style x:Key="BodyStyle" TargetType="Label">
<Setter Property="FontSize" Value="16" />
<Setter Property="TextColor" Value="{StaticResource MainColor}" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="TextColor" Value="White" />
<Setter Property="Margin" Value="10" />
</Style>
</ResourceDictionary>
Finally, in App.xaml
we’ll add the reference to the new resource dictionary as follows:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
<ResourceDictionary Source="Resources/Styles/MyStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
This allows the new resource dictionary to be merged and the resources defined within it can be used throughout the application.
Throughout this post, you’ve learned what resource dictionaries are, the types of resources they can store and how to define them in different parts of a .NET MAUI project. It’s your time to practice and test this knowledge to improve your own projects.
Progress Telerik UI for .NET MAUI component library comes with a free 30-day trial.
Héctor Pérez is a Microsoft MVP with more than 10 years of experience in software development. He is an independent consultant, working with business and government clients to achieve their goals. Additionally, he is an author of books and an instructor at El Camino Dev and Devs School.