Jaa


Style Inheritance in Xamarin.Forms

Styles can inherit from other styles to reduce duplication and enable reuse.

Style inheritance in XAML

Style inheritance is performed by setting the Style.BasedOn property to an existing Style. In XAML, this is achieved by setting the BasedOn property to a StaticResource markup extension that references a previously created Style. In C#, this is achieved by setting the BasedOn property to a Style instance.

Styles that inherit from a base style can include Setter instances for new properties, or use them to override styles from the base style. In addition, styles that inherit from a base style must target the same type, or a type that derives from the type targeted by the base style. For example, if a base style targets View instances, styles that are based on the base style can target View instances or types that derive from the View class, such as Label and Button instances.

The following code demonstrates explicit style inheritance in a XAML page:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.StyleInheritancePage" Title="Inheritance" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
                <Setter Property="HorizontalOptions"
                        Value="Center" />
                <Setter Property="VerticalOptions"
                        Value="CenterAndExpand" />
            </Style>
            <Style x:Key="labelStyle" TargetType="Label"
                   BasedOn="{StaticResource baseStyle}">
                ...
                <Setter Property="TextColor" Value="Teal" />
            </Style>
            <Style x:Key="buttonStyle" TargetType="Button"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="BorderColor" Value="Lime" />
                ...
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <Label Text="These labels"
                   Style="{StaticResource labelStyle}" />
            ...
            <Button Text="So is the button"
                    Style="{StaticResource buttonStyle}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

The baseStyle targets View instances, and sets the HorizontalOptions and VerticalOptions properties. The baseStyle is not set directly on any controls. Instead, labelStyle and buttonStyle inherit from it, setting additional bindable property values. The labelStyle and buttonStyle are then applied to the Label instances and Button instance, by setting their Style properties. This results in the appearance shown in the following screenshots:

Style inheritance screenshot

Note

An implicit style can be derived from an explicit style, but an explicit style can't be derived from an implicit style.

Respecting the inheritance chain

A style can only inherit from styles at the same level, or above, in the view hierarchy. This means that:

  • An application level resource can only inherit from other application level resources.
  • A page level resource can inherit from application level resources, and other page level resources.
  • A control level resource can inherit from application level resources, page level resources, and other control level resources.

This inheritance chain is demonstrated in the following code example:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.StyleInheritancePage" Title="Inheritance" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
              ...
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <StackLayout.Resources>
                <ResourceDictionary>
                    <Style x:Key="labelStyle" TargetType="Label" BasedOn="{StaticResource baseStyle}">
                      ...
                    </Style>
                    <Style x:Key="buttonStyle" TargetType="Button" BasedOn="{StaticResource baseStyle}">
                      ...
                    </Style>
                </ResourceDictionary>
            </StackLayout.Resources>
            ...
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

In this example, labelStyle and buttonStyle are control level resources, while baseStyle is a page level resource. However, while labelStyle and buttonStyle inherit from baseStyle, it's not possible for baseStyle to inherit from labelStyle or buttonStyle, due to their respective locations in the view hierarchy.

Style inheritance in C#

The equivalent C# page, where Style instances are assigned directly to the Style properties of the required controls, is shown in the following code example:

public class StyleInheritancePageCS : ContentPage
{
    public StyleInheritancePageCS ()
    {
        var baseStyle = new Style (typeof(View)) {
            Setters = {
                new Setter {
                    Property = View.HorizontalOptionsProperty, Value = LayoutOptions.Center    },
                ...
            }
        };

        var labelStyle = new Style (typeof(Label)) {
            BasedOn = baseStyle,
            Setters = {
                ...
                new Setter { Property = Label.TextColorProperty, Value = Color.Teal    }
            }
        };

        var buttonStyle = new Style (typeof(Button)) {
            BasedOn = baseStyle,
            Setters = {
                new Setter { Property = Button.BorderColorProperty, Value =    Color.Lime },
                ...
            }
        };
        ...

        Content = new StackLayout {
            Children = {
                new Label { Text = "These labels", Style = labelStyle },
                ...
                new Button { Text = "So is the button", Style = buttonStyle }
            }
        };
    }
}

The baseStyle targets View instances, and sets the HorizontalOptions and VerticalOptions properties. The baseStyle is not set directly on any controls. Instead, labelStyle and buttonStyle inherit from it, setting additional bindable property values. The labelStyle and buttonStyle are then applied to the Label instances and Button instance, by setting their Style properties.