Using styles in Xamarin.Forms

Styles are used to group a set of property settings, which can be applied to visual elements in a view. A style works very much the same way as a class in CSS, and is a great way to avoid duplicated code by using references instead of hard coded values. In this article I will show you how to work with style tags, and how to apply them to elements. Style support was added to Xamarin.Forms 1.3.0.

Xamarin.Forms 1.3.0 Pre-release

At the time of writing, Xamarin.Forms version 1.3.0 is in pre-release. You can download the Nu-Get packaged needed to follow this example from here. You will need to drop the binding to the version of Xamarin.Forms you are currently using, and retarget all of your projects to use the Xamarin.Forms 1.3.0 pre-release assembly:

Xamarin 1.3 NuGet

At this point in time, the final syntax for style support has not been fully decided. This article is based on the 1.3.0 pre-release, so please be aware that the syntax might change in later versions.

Styles

In order to make a style, we first have to create a view with a set of controls that we can apply our styles to. For this example, I have set up a ContentPage with a StackLayout containing two Label elements:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="XamarinTests.Views.StylesTestpage">
<ContentPage.Content>
  <StackLayout>
  	<Label Text="Header" />
  	<Label Text="Bodytext value" />
  </StackLayout>
</ContentPage.Content>
</ContentPage>

First we have to create a container to hold our styles. For this we will need a ResourceDictionary at the root level of the page. By defining our ResourceDictionary at the root level, we will be able to access our styles from all of our elements on the page. We define our ResourceDictionary in the Resources property of the ContentPage element:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="XamarinTests.Views.StylesTestpage">
  <ContentPage.Resources>
		<ResourceDictionary>
		</ResourceDictionary>
  </ContentPage.Resources>
<ContentPage.Content>
  <StackLayout>
  	<Label Text="Header" />
  	<Label Text="Bodytext value" />
  </StackLayout>
</ContentPage.Content>
</ContentPage>

 

Now that we have our container, we are ready to add some styles. We do that by defining a Style element inside of our ResourceDictionary. For this demo, we will add a style for the header and a style for the bodytext:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="XamarinTests.Views.StylesTestpage">
  <ContentPage.Resources>
		<ResourceDictionary>
		      <Style x:Key="blueTextHeadline" TargetType="Label">
		        <Setter Property="Label.TextColor" Value="Blue" />
		        <Setter Property="Label.HorizontalOptions" Value="Center" />
		        <Setter Property="Label.FontSize" Value="30" />
		      </Style>
			  <Style x:Key="bodyText" TargetType="Label">
			  	<Setter Property="Label.TextColor" Value="Red" />
			  </Style>
		</ResourceDictionary>
  </ContentPage.Resources>
<ContentPage.Content>
  <StackLayout>
  	<Label Text="Header" />
  	<Label Text="Bodytext value" />
  </StackLayout>
</ContentPage.Content>
</ContentPage>

 

You might be wondering why we have to specify the full path to the property we want to modify inside the Setter element in our Style tag, since we have already defined that our style should target Label elements. This is a requirement in the pre-release version of the Xamarin.Forms 1.3.0 and is subject to change. Besides this, the Setter elements are used in the same way as they are used in the Microsoft ecosystem. If we test the app now, we get the following:

Top level styles not applied

We have not yet defined the link between our Label elements and the style we want to apply. To do this, we will add a static reference to the element we want to style using the standard StaticResource syntax:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="XamarinTests.Views.StylesTestpage">
  <ContentPage.Resources>
		<ResourceDictionary>
		      <Style x:Key="blueTextHeadline" TargetType="Label">
		        <Setter Property="Label.TextColor" Value="Blue" />
		        <Setter Property="Label.HorizontalOptions" Value="Center" />
		        <Setter Property="Label.FontSize" Value="30" />
		      </Style>
			  <Style x:Key="bodyText" TargetType="Label">
			  	<Setter Property="Label.TextColor" Value="Red" />
			  </Style>
		</ResourceDictionary>
  </ContentPage.Resources>
<ContentPage.Content>
  <StackLayout>
  	<Label Text="Header" Style="{StaticResource blueTextHeadline}" />
  	<Label Text="Bodytext value" Style="{StaticResource bodyText}" />
  </StackLayout>
</ContentPage.Content>
</ContentPage>

 

If we test the app again, we get the following:

Top level styles applied

Inherited styles

It is also possible to inherit from other styles, to avoid repeated code. This is done by linking the BasedOn property on a style to the style you want to use as the base style using a StaticResource reference. We can change to code to make a new style, inheritedTextStyle, which will use the bodyText style as its base style:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="XamarinTests.Views.StylesTestpage">
  <ContentPage.Resources>
		<ResourceDictionary>
		      <Style x:Key="blueTextHeadline" TargetType="Label">
		        <Setter Property="Label.TextColor" Value="Blue" />
		        <Setter Property="Label.HorizontalOptions" Value="Center" />
		        <Setter Property="Label.FontSize" Value="30" />
		      </Style>
			  <Style x:Key="bodyText" TargetType="Label">
			  	<Setter Property="Label.TextColor" Value="Red" />
			  </Style>
			  <Style x:Key="interitedTextStyle" TargetType="Label" BasedOn="{StaticResource bodyText}">
			  	<Setter Property="Label.FontSize" Value="40" />
			  </Style>
		</ResourceDictionary>
  </ContentPage.Resources>
<ContentPage.Content>
  <StackLayout>
  	<Label Text="Header" Style="{StaticResource blueTextHeadline}" />
  	<Label Text="Bodytext value" Style="{StaticResource interitedTextStyle}" />
  </StackLayout>
</ContentPage.Content>
</ContentPage>

 

If we test the app again, we get the following:

Top level style and intrited style applied

Global level styles

At this point, it is not possible to link a ResourceDictionary residing in a XAML file outside of a specific page, like it is the Microsoft XAML implementation. The only way to create global level styles at the time of writing is to add a ResourceDictionary to the Resources member of the App entry point class like so:

using Xamarin.Forms;
using XamarinTests.Views;

namespace XamarinTests
{
    public class App : Application
    {
		public App ()
		{
			MainPage = new StylesTestpage ();
			Resources = new ResourceDictionary (); //Global level ResourceDictionary
		}

    }
}

 

The problem with this approach is, that we can only make one ResourceDictionary, and not break our styling into multiple files. Also, we cannot define our styles in XAML using this approach. The Xamarin team is aware of this issue, and hopefully it will be fixed for the final release of 1.3.0.

comments powered by Disqus