Telerik blogs

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!

What Is a Resource Dictionary?

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:

  • Styles
  • Colors
  • Control templates
  • Data templates
  • Triggers
  • Visual states
  • Converters
  • And many others

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.

What Is the Advantage of Using Resource Dictionaries?

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.

Defining Resource Dictionaries at the View Level

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:

The application showing styles applied to controls using Resource Dictionaries

Declaring Resource Dictionaries at the Layout Level

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.

Adding Keys to Styles

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.

Adding Resources at the Page and Application Level

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 ContentPages, 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:

The template selected in Visual Studio 2022 to create a new resource dictionary

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.

Conclusion

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.

Try Telerik UI for .NET MAUI


About the Author

Héctor Pérez

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.

 

Related Posts

Comments

Comments are disabled in preview mode.
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy