Estilos dinámicos en Xamarin.Forms
Los estilos no responden a los cambios de propiedad y permanecen sin cambios durante la duración de una aplicación. Por ejemplo, después de asignar un estilo a un elemento visual, si se modifica o se quita cualquiera de las instancias de Setter, o se agrega una instancia nueva de Setter, los cambios no se aplicarán a este elemento. Sin embargo, las aplicaciones pueden responder a los cambios de estilo dinámicamente en tiempo de ejecución mediante recursos dinámicos.
La extensión de marcado DynamicResource
es similar a la extensión de marcado StaticResource
en que ambos usan una clave de diccionario para capturar un valor de ResourceDictionary
. Pero mientras StaticResource
realiza una búsqueda de diccionario única, DynamicResource
mantiene un vínculo a la clave del diccionario. Por lo tanto, si se reemplaza la entrada del diccionario asociada a la clave, el cambio se aplica al elemento visual. Esto permite realizar cambios de estilo en tiempo de ejecución en una aplicación.
En el código de ejemplo siguiente se muestran estilos dinámicos 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.DynamicStylesPage" Title="Dynamic" IconImageSource="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
...
</Style>
<Style x:Key="blueSearchBarStyle"
TargetType="SearchBar"
BasedOn="{StaticResource baseStyle}">
...
</Style>
<Style x:Key="greenSearchBarStyle"
TargetType="SearchBar">
...
</Style>
...
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<SearchBar Placeholder="These SearchBar controls"
Style="{DynamicResource searchBarStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
Las instancias de SearchBar
usan la extensión de marcado DynamicResource
para hacer referencia a un elemento de Style
denominado searchBarStyle
, que no está definido en el XAML. Sin embargo, dado que las propiedades de Style
de las instancias de SearchBar
se establecen mediante DynamicResource
, la clave de diccionario que falta no genera una excepción.
En su lugar, en el archivo de código subyacente, el constructor crea una entrada de ResourceDictionary
con la clave searchBarStyle
, como se muestra en el código de ejemplo siguiente:
public partial class DynamicStylesPage : ContentPage
{
bool originalStyle = true;
public DynamicStylesPage ()
{
InitializeComponent ();
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
}
void OnButtonClicked (object sender, EventArgs e)
{
if (originalStyle) {
Resources ["searchBarStyle"] = Resources ["greenSearchBarStyle"];
originalStyle = false;
} else {
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
originalStyle = true;
}
}
}
Cuando se ejecute el controlador de eventos OnButtonClicked
, searchBarStyle
cambiará entre blueSearchBarStyle
y greenSearchBarStyle
. El resultado es el aspecto que se muestra en las capturas de pantalla siguientes:
En el ejemplo de código siguiente se muestra la página equivalente en C#:
public class DynamicStylesPageCS : ContentPage
{
bool originalStyle = true;
public DynamicStylesPageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
...
var searchBar1 = new SearchBar { Placeholder = "These SearchBar controls" };
searchBar1.SetDynamicResource (VisualElement.StyleProperty, "searchBarStyle");
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
Content = new StackLayout {
Children = { searchBar1, searchBar2, searchBar3, searchBar4, button }
};
}
...
}
En C#, las instancias de SearchBar
usan el método SetDynamicResource
para hacer referencia a searchBarStyle
. El código del controlador de eventos OnButtonClicked
es idéntico al ejemplo XAML y, cuando se ejecuta, searchBarStyle
cambiará entre blueSearchBarStyle
y greenSearchBarStyle
.
Herencia de estilo dinámico
La derivación de estilo de un estilo dinámico no se puede lograr mediante la propiedad Style.BasedOn
. En su lugar, la clase Style
incluye la propiedad BaseResourceKey
, que se puede establecer en una clave de diccionario cuyo valor podría cambiar de manera dinámica.
En el código de ejemplo siguiente se muestra la herencia del estilo dinámico 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.DynamicStylesInheritancePage" Title="Dynamic Inheritance" IconImageSource="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
...
</Style>
<Style x:Key="blueSearchBarStyle" TargetType="SearchBar" BasedOn="{StaticResource baseStyle}">
...
</Style>
<Style x:Key="greenSearchBarStyle" TargetType="SearchBar">
...
</Style>
<Style x:Key="tealSearchBarStyle" TargetType="SearchBar" BaseResourceKey="searchBarStyle">
...
</Style>
...
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<SearchBar Text="These SearchBar controls" Style="{StaticResource tealSearchBarStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
Las instancias de SearchBar
usan la extensión de marcado StaticResource
para hacer referencia a un objeto Style
denominado tealSearchBarStyle
. Style
establece algunas propiedades adicionales y usa la propiedad BaseResourceKey
para hacer referencia a searchBarStyle
. La extensión de marcado DynamicResource
no es necesaria porque tealSearchBarStyle
no cambiará, a excepción de Style
, del que deriva. Por lo tanto, tealSearchBarStyle
mantiene un vínculo a searchBarStyle
y se modifica cuando cambia el estilo base.
En el archivo de código subyacente, el constructor crea una entrada de ResourceDictionary
con la clave searchBarStyle
, según el ejemplo anterior que mostró estilos dinámicos. Cuando se ejecute el controlador de eventos OnButtonClicked
, searchBarStyle
cambiará entre blueSearchBarStyle
y greenSearchBarStyle
. El resultado es el aspecto que se muestra en las capturas de pantalla siguientes:
En el ejemplo de código siguiente se muestra la página equivalente en C#:
public class DynamicStylesInheritancePageCS : ContentPage
{
bool originalStyle = true;
public DynamicStylesInheritancePageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var tealSearchBarStyle = new Style (typeof(SearchBar)) {
BaseResourceKey = "searchBarStyle",
...
};
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
Content = new StackLayout {
Children = {
new SearchBar { Text = "These SearchBar controls", Style = tealSearchBarStyle },
...
}
};
}
...
}
tealSearchBarStyle
se asigna directamente a la propiedad Style
de las instancias de SearchBar
. Este elemento Style
establece algunas propiedades adicionales y usa la propiedad BaseResourceKey
para hacer referencia a searchBarStyle
. El método SetDynamicResource
no es necesario aquí porque tealSearchBarStyle
no cambiará, excepto el Style
del que deriva. Por lo tanto, tealSearchBarStyle
mantiene un vínculo a searchBarStyle
y se modifica cuando cambia el estilo base.