January 23rd, 2018

Better Resource Organization in Xamarin.Forms

David Ortinau
Principal Product Manager

Resource Dictionary is a foundational building block to all Xamarin.Forms mobile development. It’s the primary vehicle for declaring XAML resources you’ll use throughout your mobile application, including everything from styles to value converters, content templates, and data templates. In the most recent stable release of Xamarin.Forms, we gained the ability to merge multiple resource dictionaries for even greater flexibility in composing resources. In this article, I’ll show you how to take advantage of that and give you a glimpse at some of the new syntax improvements coming your way.

Merged Dictionaries

Out with the Old

Prior to 2.5.0, you probably found yourself implementing a single resource dictionary per ContentPage or other control. Every control has a Resources property of type ResourceDictionary where you declare reusable resources.

<Application ...>
    <Application.Resources>
        <ResourceDictionary>
            <Color x:Key="PageBackgroundColor">Yellow</Color>
            <Color x:Key="HeadingTextColor">Black</Color>
            <Color x:Key="NormalTextColor">Blue</Color>
            <Style x:Key="LabelPageHeadingStyle" TargetType="Label">
                <Setter Property="FontAttributes" Value="Bold" />
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

You might define colors and styles that you wish to use throughout your application at the Application level in this code.

If you’re really industrious, you might have discovered that you merge one dictionary with another using the MergedWith property.

<Application ...
    xmlns:local="using:MyApplication">
    <Application.Resources>
        <ResourceDictionary MergedWith="local:Colors">
        <Style x:Key="LabelPageHeadingStyle" TargetType="Label">
            <Setter Property="FontAttributes" Value="Bold" />
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
        </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

In this example the primary dictionary is being merged with another resource dictionary of colors.

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="MyApplication.Colors">
    <Color x:Key="PageBackgroundColor">Yellow</Color>
    <Color x:Key="HeadingTextColor">Black</Color>
    <Color x:Key="NormalTextColor">Blue</Color>
</ResourceDictionary>

Using a ResourceDictionary in this fashion requires a code file to declare the class.

...

public partial class Colors : ResourceDictionary
{
  ...
}

In with the New

This syntax gets much cleaner with the new implementation of merged dictionaries, and you can merge multiple dictionaries instead of just the one. Instead of using MergedWith, you now add to a new MergedDictionaries collection property.

<Application ...
    xmlns:local="using:MyApplication">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <local:Colors />
                <!-- Add more resource dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <Style x:Key="LabelPageHeadingStyle" TargetType="Label">
                <Setter Property="FontAttributes" Value="Bold" />
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

A big thanks to Microsoft MVP Adam Pedley for his proposal and initial pull request for merged dictionaries and for working with us to make this happen.

Upcoming ResourceDictionary Improvements

The next major version of Xamarin.Forms will introduce several improvements to ResourceDictionary in XAML, which you can get a taste for now in the nightly build feed.

Pure XAML ResourceDictionaries You’ll notice the Colors.xaml needs to have a partial class to accompany it in the example above, even though it’s totally empty. That’s no longer required in the nightly build, where you can declare a XAML file without any Class and it will still be compiled with XAML.

Here’s another file Colors.xaml example, which contains all the colors to be used in an application. The <?xaml-comp compile=”true” ?>  does the magic.

<?xml version="1.0" encoding="utf-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <Color x:Key="AccentColor">#FF4B14</Color>
    <Color x:Key="BlackOpacityColor">#99253748</Color>
    <Color x:Key="BlackTextColor">#253748</Color>
    <Color x:Key="BackgroundColor">#F8F8F8</Color>
    <Color x:Key="PinkColor">#ED0241</Color>
    <Color x:Key="GrayColor">#ACB1B4</Color>
    <Color x:Key="DarkColor">#203446</Color>
    <Color x:Key="WhiteColor">#FFFFFF</Color>
    <Color x:Key="GreenColor">#368F95</Color>
</ResourceDictionary>

More Concise Syntax XAML can get pretty verbose as you declare all the resources for your application, so we’ve done some work to cut the corners and save some keystrokes. Instead of writing:

<ContentPage.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Colors.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <StyleSheet Source="style.css" />
    <Color x:Key="notgreen">FF00FF</Color>
  </ResourceDictionary>
</ContentPage.Resources>

You can simply write:

<ContentPage.Resources>
  <ResourceDictionary Source="Colors.xaml" />
  <StyleSheet Source="style.css" />
  <Color x:Key="notgreen">FF00FF</Color>
</ContentPage.Resources>

In this new syntax:

  • Source: You can now load your dictionary with the new Source property. The file should be relative to the document or absolute from the application root
  • No need to specify a top level <ResourceDictionary>, as it’s now created on demand
  • No need to specify <ResourceDictionary.MergedDictionaries> if your StyleSheet or ResourceDictionary is keyless

These improvements provide more flexibility for you to organize your application resources and compose them on a control however you need them.

Be Resourceful

Multiple merged dictionaries are available today on NuGet in the Xamarin.Forms 2.5.0 stable release. Be sure to also check out the nightly feed and explore the new features we have on the horizon.

Do you have an idea or request like Adam’s that you’d like to contribute? Start by exploring the enhancements project board on GitHub, and then open an enhancement proposal.

Author

David Ortinau
Principal Product Manager

David is a Principal Product Manager for .NET at Microsoft, focused on .NET MAUI. A .NET developer since 2002, and versed in a range of programming languages, David has developed web, environmental, and mobile experiences for a wide variety of industries. After several successes with tech startups and running his own software company, David joined Microsoft to follow his passion: crafting tools that help developers create better app experiences. When not at a computer or with his family, David ...

More about author

0 comments

Discussion are closed.