Clases de estilo de Xamarin.Forms

Las clases de estilo de Xamarin.Forms permiten aplicar varios estilos a un control, sin tener que recurrir a la herencia de estilos.

Creación de clases de estilo

Se puede crear una clase de estilo estableciendo la propiedad Class en un objeto Stylestring que representa el nombre de clase. La ventaja que ofrece, sobre la definición de un estilo explícito mediante el atributo x:Key, es que se pueden aplicar varias clases de estilo a VisualElement.

Importante

Varios estilos pueden compartir el mismo nombre de clase, siempre que tengan como destino tipos diferentes. Esto permite que varias clases de estilo, que tienen un nombre idéntico, tienen como destino tipos diferentes.

En el ejemplo siguiente se muestran tres clases de estilo BoxView y una clase de estilo VisualElement:

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="BoxView"
               Class="Separator">
            <Setter Property="BackgroundColor"
                    Value="#CCCCCC" />
            <Setter Property="HeightRequest"
                    Value="1" />
        </Style>

        <Style TargetType="BoxView"
               Class="Rounded">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="10" />
        </Style>    

        <Style TargetType="BoxView"
               Class="Circle">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="WidthRequest"
                    Value="100" />
            <Setter Property="HeightRequest"
                    Value="100" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="50" />
        </Style>

        <Style TargetType="VisualElement"
               Class="Rotated"
               ApplyToDerivedTypes="true">
            <Setter Property="Rotation"
                    Value="45" />
        </Style>        
    </ContentPage.Resources>
</ContentPage>

Las clases de estilo Separator, Rounded y Circle establecen propiedades BoxView en valores específicos.

La clase de estilo Rotated tiene un elemento TargetType de VisualElement, lo que significa que solo se puede aplicar a instancias de VisualElement. Sin embargo, su propiedad ApplyToDerivedTypes se establece en true, lo que garantiza que se puede aplicar a cualquier control que derive de VisualElement, como BoxView. Para más información sobre cómo aplicar un estilo a un tipo derivado, consulta Aplicación de un estilo a tipos derivados.

El código de C# equivalente es el siguiente:

var separatorBoxViewStyle = new Style(typeof(BoxView))
{
    Class = "Separator",
    Setters =
    {
        new Setter
        {
            Property = VisualElement.BackgroundColorProperty,
            Value = Color.FromHex("#CCCCCC")
        },
        new Setter
        {
            Property = VisualElement.HeightRequestProperty,
            Value = 1
        }
    }
};

var roundedBoxViewStyle = new Style(typeof(BoxView))
{
    Class = "Rounded",
    Setters =
    {
        new Setter
        {
            Property = VisualElement.BackgroundColorProperty,
            Value = Color.FromHex("#1FAECE")
        },
        new Setter
        {
            Property = View.HorizontalOptionsProperty,
            Value = LayoutOptions.Start
        },
        new Setter
        {
            Property = BoxView.CornerRadiusProperty,
            Value = 10
        }
    }
};

var circleBoxViewStyle = new Style(typeof(BoxView))
{
    Class = "Circle",
    Setters =
    {
        new Setter
        {
            Property = VisualElement.BackgroundColorProperty,
            Value = Color.FromHex("#1FAECE")
        },
        new Setter
        {
            Property = VisualElement.WidthRequestProperty,
            Value = 100
        },
        new Setter
        {
            Property = VisualElement.HeightRequestProperty,
            Value = 100
        },
        new Setter
        {
            Property = View.HorizontalOptionsProperty,
            Value = LayoutOptions.Start
        },
        new Setter
        {
            Property = BoxView.CornerRadiusProperty,
            Value = 50
        }
    }
};

var rotatedVisualElementStyle = new Style(typeof(VisualElement))
{
    Class = "Rotated",
    ApplyToDerivedTypes = true,
    Setters =
    {
        new Setter
        {
            Property = VisualElement.RotationProperty,
            Value = 45
        }
    }
};

Resources = new ResourceDictionary
{
    separatorBoxViewStyle,
    roundedBoxViewStyle,
    circleBoxViewStyle,
    rotatedVisualElementStyle
};

Consumo de clases de estilo

Las clases de estilo se pueden consumir estableciendo la propiedad StyleClass del control, que es de tipo IList<string>, en una lista de nombres de clase de estilo. Se aplicarán las clases de estilo, siempre que el tipo del control coincida con el TargetType de las clases de estilo.

En el ejemplo siguiente se muestran tres instancias de BoxView, cada una establecida en clases de estilo diferentes:

<ContentPage ...>
    <ContentPage.Resources>
        ...
    </ContentPage.Resources>
    <StackLayout Margin="20">
        <BoxView StyleClass="Separator" />       
        <BoxView WidthRequest="100"
                 HeightRequest="100"
                 HorizontalOptions="Center"
                 StyleClass="Rounded, Rotated" />
        <BoxView HorizontalOptions="Center"
                 StyleClass="Circle" />
    </StackLayout>
</ContentPage>    

En este ejemplo, el primer elemento BoxView tiene el estilo de separador de línea, mientras que el tercer elemento BoxView es circular. El segundo elemento BoxView tiene dos clases de estilo aplicadas, que le dan esquinas redondeadas y lo giran 45 grados:

BoxViews tiene el estilo de las clases de estilo

Importante

Se pueden aplicar varias clases de estilo a un control porque la propiedad StyleClass es de tipo IList<string>. Cuando esto ocurre, las clases de estilo se aplican en orden de lista ascendente. Por lo tanto, cuando varias clases de estilo establecen propiedades idénticas, la propiedad de la clase de estilo que se encuentra en la posición de lista más alta tendrá prioridad.

El código de C# equivalente es el siguiente:

...
Content = new StackLayout
{
    Children =
    {
        new BoxView { StyleClass = new [] { "Separator" } },
        new BoxView { WidthRequest = 100, HeightRequest = 100, HorizontalOptions = LayoutOptions.Center, StyleClass = new [] { "Rounded", "Rotated" } },
        new BoxView { HorizontalOptions = LayoutOptions.Center, StyleClass = new [] { "Circle" } }
    }
};