Herencia de estilos en Xamarin.Forms
Los estilos se pueden heredar de otros estilos para reducir la duplicación y habilitar la reutilización.
Herencia de estilos en XAML
La herencia de estilos se realiza mediante el establecimiento de la propiedad Style.BasedOn
en un elemento Style
existente. En XAML, esto se logra al establecer la propiedad BasedOn
en una extensión de marcado StaticResource
que hace referencia a una instancia de Style
creada anteriormente. En C#, esto se logra al establecer la propiedad BasedOn
en una instancia de Style
.
Los estilos que heredan de un estilo base pueden incluir instancias Setter
para nuevas propiedades o usarlos para invalidar estilos del estilo base. Además, los estilos que heredan de un estilo base deben tener como destino el mismo tipo o un tipo que derive del tipo destinado al estilo base. Por ejemplo, si un estilo base tiene como destino instancias de View
, los estilos basados en el estilo base pueden tener como destino instancias de View
o tipos que derivan de la clase View
, como las instancias de Label
y Button
.
En el código siguiente se muestra la herencia de estilos explícita en una página XAML:
<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>
baseStyle
tiene como destino instancias de View
y establece las propiedades HorizontalOptions
y VerticalOptions
. baseStyle
no está establecido directamente en ningún control. En su lugar, labelStyle
y buttonStyle
heredan de él, estableciendo valores de propiedad enlazables adicionales. Después, labelStyle
y buttonStyle
se aplican a las instancias de Label
y a la instancia de Button
, mediante el establecimiento de sus propiedades Style
. El resultado es el aspecto que se muestra en las capturas de pantalla siguientes:
Nota:
Un estilo implícito se puede derivar de un estilo explícito, pero un estilo explícito no se puede derivar de un estilo implícito.
Respeto de la cadena de herencia
Un estilo solo puede heredar de estilos en el mismo nivel, o superior, en la jerarquía de la vista. Esto significa que:
- Un recurso de nivel de aplicación solo puede heredar de otros recursos de nivel de aplicación.
- Un recurso de nivel de página puede heredar de los recursos de nivel de aplicación y otros recursos de nivel de página.
- Un recurso de nivel de control puede heredar de recursos de nivel de aplicación, recursos de nivel de página y otros recursos de nivel de control.
Esta cadena de herencia se muestra en el ejemplo de código siguiente:
<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>
En este ejemplo, labelStyle
y buttonStyle
son recursos de nivel de control, mientras que baseStyle
es un recurso de nivel de página. Pero aunque labelStyle
y buttonStyle
heredan de baseStyle
, baseStyle
no puede heredar de labelStyle
ni buttonStyle
, debido a sus respectivas ubicaciones en la jerarquía de vistas.
Herencia de estilos en C#
En el ejemplo de código siguiente se muestra la página de C# equivalente, donde las instancias de Style
se asignan directamente a las propiedades Style
de los controles obligatorios:
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 }
}
};
}
}
baseStyle
tiene como destino instancias de View
y establece las propiedades HorizontalOptions
y VerticalOptions
. baseStyle
no está establecido directamente en ningún control. En su lugar, labelStyle
y buttonStyle
heredan de él, estableciendo valores de propiedad enlazables adicionales. Después, labelStyle
y buttonStyle
se aplican a las instancias de Label
y a la instancia de Button
, mediante el establecimiento de sus propiedades Style
.