Extensión de marcado {ThemeResource}

Proporciona un valor para cualquier atributo XAML mediante la evaluación de una referencia a un recurso, con lógica del sistema adicional que recupera distintos recursos en función del tema activo actualmente. De forma similar a la extensión de marcado {StaticResource}, los recursos se definen en resourceDictionary y un uso themeResource hace referencia a la clave de ese recurso en ResourceDictionary.

Uso del atributo XAML

<object property="{ThemeResource key}" .../>

Valores de XAML

Término Descripción
key Clave del recurso solicitado. Esta clave se asigna inicialmente mediante ResourceDictionary. Una clave de recurso puede ser cualquier cadena que se defina con la gramática XamlName.

Comentarios

ThemeResource es una técnica para obtener valores para un atributo XAML que se definen en otra parte de un diccionario de recursos XAML. La extensión de marcado tiene el mismo propósito básico que la extensión de marcado {StaticResource}. La diferencia en el comportamiento frente a la extensión de marcado {StaticResource} es que una referencia themeResource puede usar dinámicamente distintos diccionarios como ubicación de búsqueda principal, en función del tema que está usando actualmente el sistema.

Cuando se inicia la aplicación por primera vez, cualquier referencia de recurso realizada por una referencia themeResource se evalúa en función del tema que se usa en el inicio. Pero si el usuario cambia posteriormente el tema activo en tiempo de ejecución, el sistema volverá a evaluar cada referencia de ThemeResource , recuperará un recurso específico del tema que puede ser diferente y volverá a reproducir la aplicación con nuevos valores de recursos en todos los lugares adecuados del árbol visual. StaticResource se determina en tiempo de carga XAML o inicio de la aplicación y no se vuelve a evaluar en tiempo de ejecución. (Hay otras técnicas, como estados visuales que vuelven a cargar XAML dinámicamente, pero esas técnicas funcionan en un nivel superior que la evaluación básica de recursos habilitada por {StaticResource} extensión de marcado).

ThemeResource toma un argumento, que especifica la clave del recurso solicitado. Una clave de recurso siempre es una cadena en XAML de Windows Runtime. Para obtener más información sobre cómo se especifica inicialmente la clave de recurso, consulte el atributo x:Key.

Para obtener más información sobre cómo definir recursos y usar correctamente un ResourceDictionary, incluido el código de ejemplo, consulta Referencias a recursos XAML y ResourceDictionary.

Importante Como con StaticResource, un ThemeResource no debe intentar hacer una referencia directa a un recurso que se define léxicamente más dentro del archivo XAML. No se admite el intento de hacerlo. Incluso si no se produce un error en la referencia hacia delante, al intentar que se produzca una penalización de rendimiento. Para obtener los mejores resultados, ajuste la composición de los diccionarios de recursos para evitar las referencias de reenvío.

Al intentar especificar themeResource en una clave que no se puede resolver, se produce una excepción de análisis XAML en tiempo de ejecución. Las herramientas de diseño también pueden ofrecer advertencias o errores.

En la implementación del procesador XAML de Windows Runtime, no hay ninguna representación de clase de respaldo para ThemeResource. El equivalente más cercano en el código es usar la API de colección de un ResourceDictionary, por ejemplo llamando a Contains o *TryGetValue.

ThemeResource es una extensión de marcado. Las extensiones de marcado se suelen implementar cuando se necesita que los valores de los atributos de escape no sean valores literales o nombres de controladores, y este requisito es de índole más global que limitarse a colocar los convertidores de tipos en determinados tipos o propiedades. Todas las extensiones de marcado en XAML usan los caracteres "{" y "}" en su sintaxis de atributo, que es la convención por la que un procesador XAML reconoce que una extensión de marcado debe procesar el atributo.

Cuándo y cómo usar {ThemeResource} en lugar de {StaticResource}

Las reglas por las que un ThemeResource se resuelve en un elemento de un diccionario de recursos suelen ser las mismas que StaticResource. Una búsqueda ThemeResource puede extenderse a los archivos ResourceDictionary a los que se hace referencia en una colección ThemeDictionaries, pero un staticResource también puede hacerlo. La diferencia es que themeResource puede volver a evaluarse en tiempo de ejecución y un staticResource no.

El conjunto de claves de cada diccionario de temas debe proporcionar el mismo conjunto de recursos con claves, independientemente del tema que esté activo. Si existe un recurso con clave determinado en el diccionario de temas HighContrast , otro recurso con ese nombre también debe existir en Light y Default. Si no es así, es posible que se produzca un error en la búsqueda de recursos cuando el usuario cambie los temas y la aplicación no se verá bien. Aunque es posible que un diccionario de temas pueda contener recursos clave a los que solo se hace referencia desde dentro del mismo ámbito para proporcionar sub valores; estos no necesitan ser equivalentes en todos los temas.

En general, debe colocar recursos en diccionarios de temas y hacer referencias a esos recursos mediante ThemeResource solo cuando esos valores pueden cambiar entre temas o son compatibles con los valores que cambian. Esto es adecuado para estos tipos de recursos:

  • Pinceles, en particular colores para SolidColorBrush. Estos constituyen aproximadamente el 80 % de los usos de ThemeResource en las plantillas de control XAML predeterminadas (generic.xaml).
  • Valores de píxeles para bordes, desplazamientos, margen y relleno, etc.
  • Propiedades de fuente como FontFamily o FontSize.
  • Plantillas completas para un número limitado de controles que suelen ser de estilo del sistema y que se usan para la presentación dinámica, como GridViewItem y ListViewItem.
  • Estilos de presentación de texto (normalmente para cambiar el color de fuente, el fondo y posiblemente el tamaño).

Windows Runtime proporciona un conjunto de recursos diseñados específicamente para que ThemeResource haga referencia a ellos. Todos se enumeran como parte del archivo XAML themeresources.xaml, que está disponible en la carpeta include/winrt/xaml/design como parte del Kit de desarrollo de software (SDK) de Windows. Para obtener documentación sobre los pinceles de tema y los estilos adicionales que se definen en themeresources.xaml, consulta Recursos de temas XAML. Los pinceles se documentan en una tabla que indica qué valor de color tiene cada pincel para cada uno de los tres temas activos posibles.

Las definiciones XAML de estados visuales de una plantilla de control deben usar referencias a ThemeResource siempre que haya un recurso subyacente que pueda cambiar debido a un cambio de tema. Normalmente, un cambio de tema del sistema no provocará un cambio de estado visual. Los recursos deben usar referencias a ThemeResource en este caso para que los valores se puedan volver a evaluar para el estado visual todavía activo. Por ejemplo, si tiene un estado visual que cambia un color de pincel de una parte de interfaz de usuario determinada y una de sus propiedades, y ese color de pincel es diferente por tema, debe usar una referencia themeResource para proporcionar el valor de esa propiedad en la plantilla predeterminada y también cualquier modificación de estado visual en esa plantilla predeterminada.

Los usos de ThemeResource pueden verse en una serie de valores dependientes. Por ejemplo, un valor color usado por un SolidColorBrush que también es un recurso con clave podría usar una referencia ThemeResource. Pero las propiedades de la interfaz de usuario que usan el recurso SolidColorBrush con clave también usarían una referencia ThemeResource, de modo que sea específicamente cada propiedad brush-type que habilite un cambio de valor dinámico cuando cambie el tema.

Nota{ThemeResource} y la evaluación de recursos en tiempo de ejecución en el cambio de tema se admiten en XAML de Windows 8.1, pero no se admiten en XAML para aplicaciones destinadas a Windows 8.

Recursos del sistema

Algunos recursos de tema hacen referencia a los valores de recursos del sistema como subvalor subyacente. Un recurso del sistema es un valor de recurso especial que no se encuentra en ningún diccionario de recursos XAML. Estos valores se basan en el comportamiento de la compatibilidad con XAML de Windows Runtime para reenviar valores desde el propio sistema y representarlos en un formulario al que puede hacer referencia un recurso XAML. Por ejemplo, hay un recurso del sistema denominado "SystemColorButtonFaceColor" que representa un color RGB. Este color procede de los aspectos de los colores del sistema y los temas que no son solo específicos de las aplicaciones de Windows Runtime y Windows Runtime.

Los recursos del sistema suelen ser los valores subyacentes de un tema de contraste alto. El usuario controla las opciones de color de su tema de contraste alto y el usuario toma estas opciones mediante características del sistema que tampoco son específicas de las aplicaciones de Windows Runtime. Al hacer referencia a los recursos del sistema como referencias themeResource , el comportamiento predeterminado de los temas de contraste alto para las aplicaciones de Windows Runtime puede usar estos valores específicos del tema controlados por el usuario y expuestos por el sistema. Además, las referencias ahora se marcan para volver a evaluar si el sistema detecta un cambio de tema en tiempo de ejecución.

Un ejemplo de uso de {ThemeResource}

Este es un ejemplo de XAML tomado de los archivos generic.xaml y themeresources.xaml predeterminados para ilustrar cómo usar ThemeResource. Veremos solo una plantilla (el botón predeterminado) y cómo se declaran dos propiedades (fondo y primer plano) para responder a los cambios de tema.

    <!-- Default style for Windows.UI.Xaml.Controls.Button -->
    <Style TargetType="Button">
        <Setter Property="Background" Value="{ThemeResource ButtonBackgroundThemeBrush}" />
        <Setter Property="Foreground" Value="{ThemeResource ButtonForegroundThemeBrush}"/>
...

Aquí, las propiedades toman un valor Brush y la referencia a los recursos de SolidColorBrush denominados ButtonBackgroundThemeBrush y ButtonForegroundThemeBrush se realizan mediante ThemeResource.

Estas mismas propiedades también se ajustan mediante algunos de los estados visuales de un botón. En particular, el color de fondo cambia cuando se hace clic en un botón. Aquí también, las animaciones Background y Foreground del guión gráfico de estado visual usan objetos DiscreteObjectKeyFrame y referencias a pinceles con ThemeResource como valor de fotograma clave.

<VisualState x:Name="Pressed">
  <Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
        Storyboard.TargetProperty="Background">
      <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}" />
    </ObjectAnimationUsingKeyFrames>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
         Storyboard.TargetProperty="Foreground">
       <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}" />
    </ObjectAnimationUsingKeyFrames>
  </Storyboard>
</VisualState>

Cada uno de estos pinceles se define anteriormente en generic.xaml: tenían que definirse antes de las plantillas que las usan para evitar referencias de reenvío XAML. Estas son esas definiciones, para el diccionario de temas "Predeterminado".

    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Default">
...
            <SolidColorBrush x:Key="ButtonBackgroundThemeBrush" Color="Transparent" />
            <SolidColorBrush x:Key="ButtonForegroundThemeBrush" Color="#FFFFFFFF" />
...
            <SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="#FFFFFFFF" />
            <SolidColorBrush x:Key="ButtonPressedForegroundThemeBrush" Color="#FF000000" />
...

A continuación, cada uno de los otros diccionarios de temas también tiene estos pinceles definidos, por ejemplo:

        <ResourceDictionary x:Key="HighContrast">
            <!-- High Contrast theme resources -->
...
            <SolidColorBrush x:Key="ButtonBackgroundThemeBrush" Color="{ThemeResource SystemColorButtonFaceColor}" />
            <SolidColorBrush x:Key="ButtonForegroundThemeBrush" Color="{ThemeResource SystemColorButtonTextColor}" />

...
            <SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="{ThemeResource SystemColorButtonTextColor}" />
            <SolidColorBrush x:Key="ButtonPressedForegroundThemeBrush" Color="{ThemeResource SystemColorButtonFaceColor}" />

Aquí el valor Color es otra referencia themeResource a un recurso del sistema. Si hace referencia a un recurso del sistema y quiere que cambie en respuesta a un cambio de tema, debe usar ThemeResource para hacer la referencia.

Comportamiento de Windows 8

Windows 8 no admitía la extensión de marcado ThemeResource , ya que está disponible a partir de Windows 8.1. Además, Windows 8 no admiteba el cambio dinámico de los recursos relacionados con el tema para una aplicación de Windows Runtime. La aplicación tenía que reiniciarse para seleccionar el cambio de tema para las plantillas y estilos XAML. Esto no es una buena experiencia de usuario, por lo que se recomienda encarecidamente a las aplicaciones volver a compilar y dirigirse a Windows 8.1 para que puedan usar estilos con usos de ThemeResource y puedan cambiar dinámicamente los temas cuando el usuario lo hace. Las aplicaciones compiladas para Windows 8, pero que se ejecutan en Windows 8.1 siguen usando el comportamiento de Windows 8.

Compatibilidad con herramientas en tiempo de diseño para la extensión de marcado {ThemeResource}

Microsoft Visual Studio 2013 puede incluir posibles valores de clave en las listas desplegables de Microsoft IntelliSense cuando se usa la extensión de marcado {ThemeResource} en una página XAML. Por ejemplo, en cuanto escribas "{ThemeResource", se muestran las claves de recursos de los recursos del tema XAML.

Una vez que existe una clave de recurso como parte de cualquier uso de {ThemeResource} , la característica Ir a definición (F12) puede resolver ese recurso y mostrar el archivo generic.xaml para tiempo de diseño, donde se define el recurso de tema. Dado que los recursos de tema se definen más de una vez (por tema) Ir a definición le lleva a la primera definición que se encuentra en el archivo, que es la definición de Default. Si desea las otras definiciones, puede buscar el nombre de clave en el archivo y buscar las definiciones de otros temas.