Styling in XAML in Xamarin Forms has always been less than perfect in my eyes when trying to define and organize styles for your app.
In early 2015 I blogged about putting Styles in the App.xaml in Application.Resources to have globally accessible styles across your app. This was a great place to start, having some global styles and then locally define styles in each pages’ Application.Resources. Easy App Theming for Xamarin.Forms nicely details this process. However merged dictionaries like WPF would really enhance the capabilities.
At Evolve 2016 as I watched the live stream they announced Themes but what popped out in their code sample was ‘MergedWith’ and my instant response.
#xamarinforms – Merged Dictionaries, woohoo!
— Adam Pedley (@adpedley) April 27, 2016
What are Merged Dictionaries?
They are the ability to merge dictionaries together from different sources. Think of it as importing CSS into a style. This functionality starts with version 2.3.0 of Xamarin.Forms, make sure you are using this version or higher.
Lets Create a Theme
Create a new XAML page and create a ResourceDictionary
<?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="UIDemo.Style.NewStyle"> <Style TargetType="Label"> <Setter Property="TextColor" Value="Blue" /> </Style> </ResourceDictionary>
namespace UIDemo.Style { public partial class NewStyle { public NewStyle() { InitializeComponent(); } } }
Apply the Theme
Now we can merge the dictionary with one on the page and voila, a merged dictionary.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:theme="clr-namespace:UIDemo.Style" x:Class="UIDemo.MainPage"> <ContentPage.Resources> <ResourceDictionary MergedWith="theme:NewStyle" /> </ContentPage.Resources> <Grid> <Label Text="Hello" /> </Grid> </ContentPage>
Mobile Developer | Build Flutter
One important thing to mention about merged dictionaries support in Xamarin Forms is you can’t merge multiple dictionaries.
This is useful when you want to keep resource dictionaries separate in different files for maintainability.
In WPF you can do this:
But in Xamarin Forms you only have a `MergedWith` attribute which takes only one resource dictionary.
Yes, unfortunately that is a limitation. Hopefully it might be removed in the future.
For some reason the WPF example got removed:
I think the commenting system automatically removes xml/html tags. e.g. < and > You need to do the html encoded formatting to have them display.
hi
is there a way not to create a partial class and add a simple xaml file and all the resources in there and then add it to the dictionary later ?
something like ( this example is used from WPF)
Current.Resources.MergedDictionaries.Add(new ResourceDictionary
{
Source = new Uri(@”/UIModule;component/Presentment/PresentmentTemplates.xaml”, UriKind.RelativeOrAbsolute)
});
Hi , Thanks for the post..!
But i didn’t got the meaning of “Create a new XAML page and create a ResourceDictionary” , what i guess is that , we need to add xamal page first then convert it to the ResourceDictionary,
is it correct ?
A ResourceDictionary is a property on a Page or Application. In your App.cs or MyPage.cs you can add a ResourceDictionary.
<Application.Resources>
<ResourceDictionary>
</ResourceDictionary>
</Application.Resources>
or in codebehind you can do
this.Resources.Add(….);
How to reference the Resource Dictionary from the App.xaml.cs instead of App.Xaml.?
Use this.Resources in your code. As an example you can add to it like:
this.Resources.Add(“key”, “value”);
I need to add a resource dictionary from code behind not the resources. The Merged with tag available in design mode is accessible in code behind but not sure of how to read and pass the style xaml being created to it from code behind.
You need to create a new ResourceDictionary class
public class MyCustomResourceDictionary : ResourceDictionary
{
public MyRD()
{
Add(“key”, “value”);
}
}
Then add it to MergedWith via
this.Resources.MergedWith = typeof(MyCustomResourceDictionary);
Thanks for the help. It works like a charm !!.
One more help I am trying to read the XAML from the app.config in PCL using PCLAppconfig nuget package but unable to add that in this.Resources.MergedWith = typeof(MyCustomResourceDictionary); post that. Any way we can read that fileName as a xaml in code behind something like XAMLReader we do in WPF.
If you add an x:Name attribute you may be able to get a reference to it from code behind. If not, when the XAML has loaded, you should be able to get a reference to it from the existing ResourceDictionary, if you have already added it somewhere in XAML.
If you needed to load the XAML from a string, there is nothing publicly available, however the XamlLoader in Xamarin Forms can be taken from source control and used. You will need to go to the Xamarin Forms source code on GitHub for that.
Hi adam.
My requirement is to create multiple resource dictionary files and use them one at a time by passing the Resource Dictionary in app.config at build time.
I have achieved the same in WPF using
if (!string.IsNullOrEmpty(fileName))
{
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
// Read in ResourceDictionary File
ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
// Clear any previous dictionaries loaded
Resources.MergedDictionaries.Clear();
// Add in newly loaded Resource Dictionary
Resources.MergedDictionaries.Add(dic);
}
}
But for xamarin forms am unable to get to the bottom of it.
You can’t have multiple merged dictionaries. I currently have an evolution API request in with Xamarin, to enable it, but you can only have one MergedWith. However if you want to dynamically add one style at a time, at runtime, you can do it with DynamicResources: https://developer.xamarin.com/guides/xamarin-forms/user-interface/styles/dynamic/