Diccionarios de recursos

Una interfaz de usuario de aplicación multiplataforma de .NET (.NET MAUI) ResourceDictionary es un repositorio para los recursos que usa una aplicación .NET MAUI. Los recursos típicos que se almacenan en un ResourceDictionary incluyen estilos, plantillas de control, plantillas de datos, convertidores y colores.

Se puede hacer referencia a los recursos XAML almacenados en un ResourceDictionary objeto y aplicarlos a elementos mediante la StaticResource extensión de marcado o DynamicResource . En C#, los recursos también se pueden definir en y ResourceDictionary , a continuación, hacer referencia y aplicar a elementos mediante un indexador basado en cadenas. Sin embargo, hay poca ventaja de usar en ResourceDictionary C#, ya que los objetos compartidos se pueden almacenar como campos o propiedades, y se tiene acceso directamente sin tener que recuperarlos primero de un diccionario.

Sugerencia

En Visual Studio, la plantilla de elemento ResourceDictionary (XAML) de .NET MAUI resourceDictionary (XAML) puede agregar un archivo basado en ResourceDictionary XAML que esté respaldado por un archivo de código subyacente.

Crear recursos

Cada VisualElement objeto derivado tiene una Resources propiedad , que es un ResourceDictionary objeto que puede contener recursos. Del mismo modo, un Application objeto derivado tiene una Resources propiedad , que es un ResourceDictionary objeto que puede contener recursos.

Una aplicación MAUI de .NET solo puede contener una sola clase que deriva de Application, pero a menudo hace uso de muchas clases que derivan de VisualElement, incluidas páginas, diseños y vistas. Cualquiera de estos objetos puede tener su Resources propiedad establecida en un objeto ResourceDictionary contenedor. Elegir dónde colocar un impacto determinado ResourceDictionary en el que se pueden usar los recursos:

  • Los recursos de un ResourceDictionary que está asociado a una vista, como Button o Label, solo se pueden aplicar a ese objeto en particular.
  • Los recursos de un ResourceDictionary elemento adjunto a un diseño, como StackLayout o Grid, se pueden aplicar al diseño y a todos los elementos secundarios de ese diseño.
  • Los recursos de un ResourceDictionary elemento definido en el nivel de página se pueden aplicar a la página y a todos sus elementos secundarios.
  • Los recursos de un ResourceDictionary 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 .

En el código XAML siguiente se muestran los recursos definidos en un nivel ResourceDictionary de aplicación en el archivo App.xaml :

<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             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="NavigationPage">
            <Setter Property="BarBackgroundColor"
                    Value="{StaticResource NavigationBarColor}" />
            <Setter Property="BarTextColor"
                    Value="{StaticResource NavigationBarTextColor}" />
        </Style>

        <Style TargetType="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 implícitos Style .

Importante

La inserción de recursos directamente entre las Resources etiquetas de elemento de propiedad crea automáticamente un ResourceDictionary objeto . Sin embargo, también es válido colocar todos los recursos entre etiquetas opcionales ResourceDictionary .

Consumo de recursos

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 StaticResource extensión de marcado XAML o DynamicResource .

La StaticResource extensión de marcado es similar a la DynamicResource extensión de marcado en que ambas usan una clave de diccionario para hacer referencia a un valor de un diccionario de recursos. Sin embargo, aunque la StaticResource extensión de marcado realiza una búsqueda de diccionario único, la DynamicResource extensión de marcado 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 en los recursos en tiempo de ejecución en una aplicación. Para obtener más información sobre las extensiones de marcado, consulta Extensiones de marcado XAML.

En el ejemplo XAML siguiente se muestra cómo consumir recursos y también definir un recurso adicional en :StackLayout

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ResourceDictionaryDemo.MainPage"
             Title="Main page">
    <StackLayout Margin="{StaticResource PageMargin}"
                 Spacing="6">
        <StackLayout.Resources>
            <!-- Implicit style -->
            <Style TargetType="Button">
                <Setter Property="FontSize" Value="14" />
                <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 StackLayout objeto consume el PageMargin recurso definido en el diccionario de recursos de nivel de aplicación, mientras que el Button objeto consume el estilo implícito definido en el StackLayout diccionario de recursos. Esto da como resultado la apariencia que se muestra en la captura de pantalla siguiente:

Consuming resource dictionary resources.

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 sea necesario para una página.

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 el proceso de búsqueda finaliza.
  • Si no se encuentra una coincidencia, el proceso de búsqueda busca en el árbol visual hacia arriba y comprueba el diccionario de recursos de cada elemento primario. Si se encuentra la clave solicitada, se devuelve su valor y el proceso de búsqueda finaliza. 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 de nivel de aplicación.
  • Si todavía no se encuentra una coincidencia, se produce una XamlParseException excepción .

Por lo tanto, cuando el analizador XAML encuentra una StaticResource extensión de marcado o DynamicResource , busca una clave coincidente al desplazarse por el árbol visual, usando la primera coincidencia que encuentra. Si esta búsqueda finaliza en la página y todavía no se ha encontrado la clave, el analizador XAML busca en ResourceDictionary el App objeto adjunto. Si todavía no se encuentra la clave, se produce una excepción.

Invalidar 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 AppBackgroundColor recurso AliceBlue en en el nivel de aplicación se invalidará mediante un recurso de nivel AppBackgroundColor de página establecido Tealen . Del mismo modo, un recurso de nivel de página se invalidará mediante un recurso de nivel AppBackgroundColorAppBackgroundColor de diseño o vista.

Diccionarios de recursos independientes

ResourceDictionary También se puede crear como un archivo XAML independiente que no está respaldado por un archivo de código subyacente. Para crear un archivo independiente ResourceDictionary, agregue un nuevo ResourceDictionary archivo al proyecto con la plantilla de elemento ResourceDictionary (XAML) de .NET MAUI y elimine su archivo de código subyacente. A continuación, en el archivo XAML, quite el x:Class atributo de la ResourceDictionary etiqueta cerca del inicio del archivo. Además, agregue <?xaml-comp compile="true" ?> después del encabezado XML para asegurarse de que se compilará el XAML.

Nota:

Un independiente ResourceDictionary debe tener una acción de compilación de MauiXaml.

En el ejemplo XAML siguiente se muestra un elemento independiente ResourceDictionary denominado MyResourceDictionary.xaml:

<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <DataTemplate x:Key="PersonDataTemplate">
        <ViewCell>
            <Grid RowSpacing="6"
                  ColumnSpacing="6">
                <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 mediante la combinación en otro diccionario de recursos.

Combinar diccionarios de recursos

Los diccionarios de recursos se pueden combinar combinando uno o varios ResourceDictionary objetos en otro ResourceDictionary.

Combinar diccionarios de recursos locales

Un archivo local ResourceDictionary se puede combinar en otro ResourceDictionary mediante la creación de un ResourceDictionary objeto cuya Source propiedad se establece en el nombre de 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 Source propiedad, no se requiere un archivo de código subyacente y el x:Class atributo se puede quitar de la etiqueta raíz del archivo MyResourceDictionary.xaml .

Importante

La ResourceDictionary.Source propiedad solo se puede establecer desde XAML.

Combinar diccionarios de recursos de otros ensamblados

También ResourceDictionary se puede combinar en otro ResourceDictionary agregándolo a la MergedDictionaries propiedad de ResourceDictionary. Esta técnica permite combinar diccionarios de recursos, independientemente del ensamblado en el que residen. La combinación de diccionarios de recursos de ensamblados externos requiere que ResourceDictionary una acción de compilación se establezca en MauiXaml, que tenga un archivo de código subyacente y que defina el x:Class atributo en la etiqueta raíz del archivo.

Advertencia

La clase ResourceDictionary también define una propiedad MergedWith. Sin embargo, esta propiedad ha quedado 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 MergedDictionaries colección de un nivel ResourceDictionaryde página :

<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:DefaultTheme />
                <!-- 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 ResourceDictionary objetos dentro de las MergedDictionaries etiquetas property-element y otros recursos fuera de esas etiquetas.

Importante

Solo puede haber una MergedDictionaries etiqueta de elemento de propiedad en , ResourceDictionarypero puede colocar tantos ResourceDictionary objetos en allí como sea necesario.

Cuando los recursos combinados ResourceDictionary comparten valores de atributo idénticos x:Key , .NET MAUI usa la siguiente prioridad de recursos:

  1. Recursos locales para el diccionario de recursos.
  2. Los recursos contenidos en los diccionarios de recursos que se combinaron a través de la MergedDictionaries colección, en el orden inverso se muestran en la MergedDictionaries propiedad .

Sugerencia

La búsqueda de diccionarios de recursos puede ser una tarea de cálculo intensivo 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.