Xamarin.Forms diccionarios de recursos
un ResourceDictionary es un repositorio para los recursos que usa una Xamarin.Forms aplicación. Los recursos típicos que se almacenan en un ResourceDictionary incluyen ResourceDictionary, plantillas de control,plantillas de datos,colores y convertidores.
En XAML, se puede hacer referencia a los recursos almacenados en y aplicar a los elementos ResourceDictionary mediante la extensión de marcado o StaticResourceDynamicResource . En C#, los recursos también se pueden definir en y, a continuación, se hace referencia a los elementos y se aplican a estos mediante un ResourceDictionary indexador basado en cadenas. Sin embargo, el uso de en C# tiene poca ventaja, ya que los objetos compartidos se pueden almacenar como campos o propiedades, y se puede acceder directamente a ellos sin tener que recuperarlos primero de un ResourceDictionary diccionario.
Creación de recursos en XAML
Cada VisualElement objeto derivado tiene una propiedad Xamarin_Forms VisualElement _VisualElement_Resources" data-linktype="absolute-path">, que es un objeto que Resources puede contener ResourceDictionary recursos. De forma similar, un objeto derivado tiene una propiedad Application Xamarin_Forms Application _VisualElement_Resources" data-linktype="absolute-path">, que es un objeto que puede contener ResourcesResourceDictionary recursos.
Una aplicación solo contiene una clase que deriva de , pero a menudo usa muchas clases que derivan de , incluidas Xamarin.FormsApplicationVisualElement páginas, diseños y controles. Cualquiera de estos objetos puede tener su Resources propiedad establecida en un recurso que ResourceDictionary contiene. Elegir dónde colocar un determinado ResourceDictionary impacto en el lugar en el que se pueden usar los recursos:
- Los recursos de
ResourceDictionaryun que está asociado a una vista como o solo se pueden aplicar a ese objetoButtonLabeldeterminado. - Los recursos de un asociado a un diseño como o se pueden aplicar al diseño y a todos
ResourceDictionarylos secundarios de eseStackLayoutGriddiseño. - Los recursos de
ResourceDictionaryun definido en el nivel de página se pueden aplicar a la página y a todos sus secundarios. - Los recursos de
ResourceDictionaryun definido en el nivel de aplicación se pueden aplicar en toda la aplicación.
A excepción de los estilos implícitos, cada recurso del diccionario de recursos debe tener una clave de cadena única definida con el x:Key atributo .
El código XAML siguiente muestra los recursos definidos en un nivel de ResourceDictionary aplicación en el archivo ResourceDictionary
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.App">
<Application.Resources>
<Thickness x:Key="PageMargin">20</Thickness>
<!-- Colors -->
<Color x:Key="AppBackgroundColor">AliceBlue</Color>
<Color x:Key="NavigationBarColor">#1976D2</Color>
<Color x:Key="NavigationBarTextColor">White</Color>
<Color x:Key="NormalTextColor">Black</Color>
<!-- Implicit styles -->
<Style TargetType="{x:Type NavigationPage}">
<Setter Property="BarBackgroundColor"
Value="{StaticResource NavigationBarColor}" />
<Setter Property="BarTextColor"
Value="{StaticResource NavigationBarTextColor}" />
</Style>
<Style TargetType="{x:Type ContentPage}"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</Application.Resources>
</Application>
En este ejemplo, el diccionario de recursos define un Thickness recurso, varios Color recursos y dos recursos Style implícitos. Para obtener más información sobre la App clase , vea Xamarin.Forms App Class .
Nota:
También es válido colocar todos los recursos entre etiquetas ResourceDictionary explícitas. Sin embargo, desde Xamarin.Forms la versión 3.0, las ResourceDictionary etiquetas no son necesarias. En su lugar, el objeto se crea automáticamente y puede insertar los recursos ResourceDictionary directamente entre las Resources etiquetas property-element.
Consumo de recursos en XAML
Cada recurso tiene una clave que se especifica mediante el x:Key atributo , que se convierte en su clave de diccionario en ResourceDictionary . La clave se usa para hacer referencia a un recurso de ResourceDictionary con la extensión de marcado o StaticResourceDynamicResource .
La extensión de marcado es similar a la extensión de marcado en que usan una clave de diccionario para hacer referencia StaticResource a un valor de un diccionario de DynamicResource recursos. Sin embargo, mientras la extensión de marcado realiza una búsqueda de diccionario única, la extensión StaticResource de marcado mantiene un vínculo a la clave del DynamicResource diccionario. Por lo tanto, si se reemplaza la entrada de diccionario asociada a la clave, el cambio se aplica al elemento visual. Esto permite realizar cambios en los recursos en tiempo de ejecución en una aplicación. Para obtener más información sobre las extensiones de marcado, vea Extensiones de marcado XAML.
En el ejemplo xaml siguiente se muestra cómo consumir recursos y también se definen recursos adicionales en StackLayout :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.HomePage"
Title="Home Page">
<StackLayout Margin="{StaticResource PageMargin}">
<StackLayout.Resources>
<!-- Implicit style -->
<Style TargetType="Button">
<Setter Property="FontSize" Value="Medium" />
<Setter Property="BackgroundColor" Value="#1976D2" />
<Setter Property="TextColor" Value="White" />
<Setter Property="CornerRadius" Value="5" />
</Style>
</StackLayout.Resources>
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries." />
<Button Text="Navigate"
Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage>
En este ejemplo, el ContentPage objeto consume el estilo implícito definido en el diccionario de recursos de nivel de aplicación. El objeto consume el recurso definido en el diccionario de recursos de nivel de aplicación, mientras que el objeto consume el estilo implícito StackLayout definido en el diccionario de PageMarginButtonStackLayout recursos. El resultado es el aspecto que se muestra en las capturas de pantalla siguientes:
Importante
Los recursos específicos de una sola página no deben incluirse en un diccionario de recursos de nivel de aplicación, ya que estos recursos se analizarán en el inicio de la aplicación en lugar de cuando lo requiera una página. Para obtener más información, vea Reducir el tamaño del diccionario de recursos de aplicación.
Comportamiento de búsqueda de recursos
El siguiente proceso de búsqueda se produce cuando se hace referencia a un recurso con la StaticResource extensión de marcado o DynamicResource :
- La clave solicitada se comprueba en el diccionario de recursos, si existe, para el elemento que establece la propiedad . Si se encuentra la clave solicitada, se devuelve su valor y finaliza el proceso de búsqueda.
- Si no se encuentra una coincidencia, el proceso de búsqueda busca en el árbol visual hacia arriba, comprobando el diccionario de recursos de cada elemento primario. Si se encuentra la clave solicitada, se devuelve su valor y finaliza el proceso de búsqueda. De lo contrario, el proceso continúa hacia arriba hasta que se alcanza el elemento raíz.
- Si no se encuentra una coincidencia en el elemento raíz, se examina el diccionario de recursos del nivel de aplicación.
- Si todavía no se encuentra una coincidencia,
XamlParseExceptionse produce una excepción .
Por lo tanto, cuando el analizador XAML encuentra una extensión de marcado o , busca una clave correspondiente recorriendo el árbol visual, usando la primera coincidencia que StaticResourceDynamicResource encuentra. Si esta búsqueda finaliza en la página y todavía no se ha encontrado la clave, el analizador XAML busca en el asociado ResourceDictionary al App objeto. Si todavía no se encuentra la clave, se produce una excepción.
Invalidación de recursos
Cuando los recursos comparten claves, los recursos definidos más abajo en el árbol visual tendrán prioridad sobre los definidos más arriba. Por ejemplo, establecer un recurso en en el AppBackgroundColor nivel de aplicación se AliceBlue reemplazará por un recurso de nivel AppBackgroundColor de página establecido en Teal . De forma similar, un recurso de AppBackgroundColor nivel de página se reemplazará por un recurso de nivel de AppBackgroundColor control.
Diccionarios de recursos independientes
Una clase derivada de ResourceDictionary también puede estar en un archivo XAML independiente. A continuación, el archivo XAML se puede compartir entre aplicaciones.
Para crear este tipo de archivo, agregue un nuevo elemento Vista de contenido o Página de contenido al proyecto (pero no una vista de contenido o una página de contenido con solo un archivo de C#). Elimine el archivo de código subyacente y, en el archivo XAML, cambie el nombre de la clase base de ContentView o ContentPage a ResourceDictionary . Además, quite el x:Class atributo de la etiqueta raíz del archivo.
En el ejemplo xaml siguiente se ResourceDictionary muestra un elemento denominado ResourceDictionary:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<DataTemplate x:Key="PersonDataTemplate">
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
TextColor="{StaticResource NormalTextColor}"
FontAttributes="Bold" />
<Label Grid.Column="1"
Text="{Binding Age}"
TextColor="{StaticResource NormalTextColor}" />
<Label Grid.Column="2"
Text="{Binding Location}"
TextColor="{StaticResource NormalTextColor}"
HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
En este ejemplo, ResourceDictionary contiene un único recurso, que es un objeto de tipo DataTemplate . MyResourceDictionary.xaml se puede consumir si se combina en otro diccionario de recursos.
De forma predeterminada, el vinculador quitará los archivos XAML independientes de las compilaciones de versión cuando el comportamiento del vinculador esté establecido para vincular todos los ensamblados. Para asegurarse de que los archivos XAML independientes permanecen en una compilación de versión:
Agregue un atributo
Preservepersonalizado al ensamblado que contiene los archivos XAML independientes. Para obtener más información, vea Conservación del código.Establezca el
Preserveatributo en el nivel de ensamblado:[assembly:Preserve(AllMembers = true)]
Para obtener más información sobre la vinculación, vea Vinculación de aplicaciones de Xamarin.iOSy Vinculación en Android.
Diccionarios de recursos combinados
Los diccionarios de recursos combinados combinan uno o varios ResourceDictionary objetos en otro ResourceDictionary .
Combinación de diccionarios de recursos locales
Un archivo local se puede combinar en otro creando un objeto cuya propiedad ResourceDictionaryResourceDictionary Xamarin_Forms ResourceDictionaryResourceDictionary _ResourceDictionary_Source" data-linktype="absolute-path">Source se establece en el nombre de archivo del archivo XAML con los recursos:
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Esta sintaxis no crea instancias de la MyResourceDictionary clase . En su lugar, hace referencia al archivo XAML. Por ese motivo, al establecer la propiedad Xamarin_Forms _ResourceDictionary_Source" data-linktype="absolute-path">, no se requiere un archivo de código subyacente y el atributo se puede quitar de la etiqueta raíz del archivo Sourcex:ClassSource
Importante
La Xamarin_Forms _ResourceDictionary_Source" data-linktype="absolute-path">propiedad solo se puede Source establecer desde XAML.
Diccionarios de recursos de combinación de otros ensamblados
También se puede combinar en otro si se agrega a la propiedad ResourceDictionaryResourceDictionary Xamarin_Forms ResourceDictionary _ResourceDictionary_MergedDictionaries" data-linktype="absolute-path">MergedDictionaries de ResourceDictionary . Esta técnica permite combinar diccionarios de recursos, independientemente del ensamblado en el que residan. La combinación de diccionarios de recursos de ensamblados externos requiere que tenga una acción de compilación establecida en EmbeddedResource , para tener un archivo de código subyacente y para definir el atributo en la etiqueta raíz del ResourceDictionaryResourceDictionaryx:Class archivo.
Advertencia
La ResourceDictionary clase también define una Xamarin_Forms ResourceDictionary _ResourceDictionary_MergedWith" data-linktype="absolute-path">MergedWith propiedad. Sin embargo, esta propiedad está en desuso y ya no se debe usar.
En el ejemplo de código siguiente se muestran dos diccionarios de recursos que se agregan a la colección de datos Xamarin_Forms _ResourceDictionary_MergedDictionaries" data-linktype="absolute-path">de un nivel de MergedDictionaries página ResourceDictionary :
<ContentPage ...
xmlns:local="clr-namespace:ResourceDictionaryDemo"
xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
<ContentPage.Resources>
<ResourceDictionary>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>
<!-- Add more resource dictionaries here -->
<local:MyResourceDictionary />
<theme:LightTheme />
<!-- Add more resource dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Add more resources here -->
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
En este ejemplo, un diccionario de recursos del mismo ensamblado y un diccionario de recursos de un ensamblado externo se combinan en el diccionario de recursos de nivel de página. Además, también puede agregar otros objetos dentro de ResourceDictionary Xamarin_Forms ResourceDictionary _ResourceDictionary_MergedDictionaries" data-linktype="absolute-path">MergedDictionaries etiquetas property-element y otros recursos fuera de esas etiquetas.
Importante
Solo puede haber una etiqueta de elemento de propiedad en , pero puede colocar tantos MergedDictionariesResourceDictionary objetos como sea ResourceDictionary necesario.
Cuando los recursos ResourceDictionary combinados comparten valores x:Key de atributo Xamarin.Forms idénticos, usa la siguiente precedencia de recursos:
- Recursos locales en el diccionario de recursos.
- Los recursos contenidos en los diccionarios de recursos que se combinaron a través de la colección, en el orden inverso, se
MergedDictionariesenumeran en la propiedadMergedDictionaries.
Nota:
La búsqueda de diccionarios de recursos puede ser una tarea que requiere muchos cálculos si una aplicación contiene varios diccionarios de recursos grandes. Por lo tanto, para evitar búsquedas innecesarias, debe asegurarse de que cada página de una aplicación solo usa diccionarios de recursos adecuados para la página.
Vínculos relacionados
- Diccionarios de recursos (ejemplo)
- Extensiones de marcado XAML
- Xamarin.Forms Styles
- Vinculación de aplicaciones de Xamarin.iOS
- Vincular en Android
- ResourceDictionary API
Descarga del ejemplo