Estensione di markup {ThemeResource}

Fornisce un valore per qualsiasi attributo XAML valutando un riferimento a una risorsa, con logica di sistema aggiuntiva che recupera risorse diverse a seconda del tema attualmente attivo. Analogamente all'estensione di {StaticResource}, le risorse vengono definite in un oggetto ResourceDictionarye un utilizzo ThemeResource fa riferimento alla chiave di quella risorsa nell'oggetto ResourceDictionary.

Utilizzo attributo XAML

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

Valori XAML

Termine Descrizione
chiave Chiave per la risorsa richiesta. Questa chiave viene inizialmente assegnata da ResourceDictionary. Una chiave di risorsa può essere qualsiasi stringa definita nella grammatica XamlName.

Osservazioni:

ThemeResource è una tecnica per ottenere valori per un attributo XAML definito altrove in un dizionario risorse XAML. L'estensione di markup assolve allo stesso scopo di base dell'estensione di markup {StaticResource}. La differenza nel comportamento rispetto all'estensione di markup {StaticResource} sta nel fatto che un riferimento ThemeResource può usare in modo dinamico dizionari diversi come percorso di ricerca principale, a seconda del tema attualmente usato dal sistema.

Al primo avvio dell'app, qualsiasi riferimento a risorse effettuato da un riferimento ThemeResource viene valutato in base al tema in uso all'avvio. Tuttavia, se successivamente l'utente modifica il tema attivo in fase di esecuzione, il sistema valuterà nuovamente ogni riferimento ThemeResource, recupererà una risorsa specifica del tema che potrebbe essere diversa e visualizzerà nuovamente l'app con nuovi valori di risorsa in tutte le posizioni appropriate nella struttura ad albero visuale. Un oggetto StaticResource viene determinato in fase di caricamento XAML/avvio dell'app e non verrà rivalutato in fase di esecuzione. Sono disponibili altre tecniche, ad esempio stati di visualizzazione che ricaricano XAML in modo dinamico, ma queste tecniche operano a un livello superiore rispetto alla valutazione delle risorse di base abilitata dall'estensione di markup {StaticResource}).

ThemeResource accetta un argomento, che specifica la chiave per la risorsa richiesta. Una chiave di risorsa è sempre una stringa in XAML di Windows Runtime. Per altre informazioni su come viene inizialmente specificata la chiave di risorsa, vedere l'attributo x:Key.

Per altre informazioni su come definire le risorse e usare correttamente un elemento ResourceDictionary, incluso il codice di esempio, vedere Riferimenti alle risorse ResourceDictionary e XAML.

Importante Come con StaticResource, un elemento ThemeResource non deve tentare un riferimento in avanti a una risorsa definita a livello lessicale nel file XAML. Questo tipo di tentativo non è supportato. Anche se il riferimento in avanti non restituisce un errore, il tentativo di crearne uno comporta una riduzione delle prestazioni. Per ottenere risultati ottimali, modificare la composizione dei dizionari risorse in modo da evitare i riferimenti in avanti.

Il tentativo di specificare un elemento ThemeResource a una chiave che non si risolve genera un'eccezione di analisi XAML in fase di esecuzione. Gli strumenti di progettazione possono anche offrire avvisi o errori.

Nell'implementazione del processore XAML di Windows Runtime non è presente alcuna rappresentazione della classe di supporto per ThemeResource. L'equivalente più vicino nel codice consiste nell'usare l'API di raccolta di un elemento ResourceDictionary, ad esempio chiamando Contains o *TryGetValue.

ThemeResource è un'estensione di markup. Le estensioni di markup in genere vengono implementate quando per i valori dell'attributo devono essere utilizzati caratteri escape in modo che non vengano considerati come valori letterali o nomi di gestori e il requisito è più globale del semplice utilizzo di convertitori dei tipi su alcuni tipi o proprietà. Tutte le estensioni di markup in XAML usano i caratteri "{" e "}" nella sintassi degli attributi, vale a dire la convenzione in base a cui il processore XAML riconosce che l'attributo deve essere elaborato da un'estensione di markup.

Quando e come usare {ThemeResource} anziché {StaticResource}

Le regole in base alle quali un elemento ThemeResource viene risolto in un elemento in un dizionario risorse sono in genere uguali a StaticResource. Una ricerca ThemeResource può estendersi in file ResourceDictionary di cui si fa riferimento in una raccolta ThemeDictionaries, tuttavia anche StaticResource può assolvere a questo scopo. La differenza sta nel fatto che un elemento ThemeResource può essere rivalutato in fase di esecuzione, mentre StaticResource no.

Il set di chiavi in ogni dizionario temi deve fornire lo stesso set di risorse con chiave, indipendentemente dal tema attivo. Se esiste una determinata risorsa con chiave nel dizionario temi HighContrast , un'altra risorsa con tale nome dovrebbe esistere anche in Light e Default. In caso contrario, la ricerca risorse potrebbe non riuscire quando l'utente cambia tema e l'app non ha un aspetto corretto. È possibile che un dizionario temi possa contenere risorse con chiave a cui viene fatto riferimento solo dall'interno dello stesso ambito per fornire valori secondari; questi non devono essere equivalenti in tutti i temi.

In generale, è consigliabile inserire le risorse in dizionari temi e fare riferimento a tali risorse usando ThemeResource solo quando questi valori possono cambiare tra temi o sono supportati dai valori che cambiano. Questo è appropriato per questi tipi di risorse:

  • Pennelli, in particolare colori per SolidColorBrush. Questi costituiscono circa l'80% degli utilizzi ThemeResource nei modelli di controllo XAML predefiniti (generic.xaml).
  • Valori pixel per bordi, offset, margine e spaziatura interna e così via.
  • Proprietà del tipo di carattere, ad esempio FontFamily o FontSize.
  • Modelli completi per un numero limitato di controlli con stili di sistema e usati per la presentazione dinamica, come GridViewItem e ListViewItem.
  • Stili di visualizzazione del testo (in genere per modificare il colore del carattere, lo sfondo e possibilmente le dimensioni).

Windows Runtime fornisce un set di risorse a cui ThemeResource deve fare riferimento in modo specifico. Sono tutte elencate come parte del file XAML themeresources.xaml, disponibile nella cartella include/winrt/xaml/design nel Windows Software Development Kit (SDK). Per la documentazione sui pennelli del tema e sugli stili aggiuntivi definiti in themeresources.xaml, vedere Risorse a tema XAML. I pennelli sono documentati in una tabella che indica il valore del colore di ogni pennello per ognuno dei tre possibili temi attivi.

Le definizioni XAML degli stati di visualizzazione in un modello di controllo devono usare riferimenti ThemeResource ogni volta che è presente una risorsa sottostante che potrebbe cambiare a causa di una modifica del tema. Una modifica del tema di sistema non comporta in genere una modifica allo stato di visualizzazione. Le risorse devono usare riferimenti a ThemeResource in questo caso in modo che sia possibile rivalutare i valori per lo stato di visualizzazione ancora attivo. Ad esempio, se si dispone di uno stato di visualizzazione che modifica il colore di un pennello di una particolare parte dell'interfaccia utente e di una delle relative proprietà e il colore del pennello cambia in base al tema, è consigliabile usare un riferimento a ThemeResource per fornire il valore della proprietà nel modello predefinito e anche qualsiasi modifica dello stato di visualizzazione a quel modello predefinito.

Gli utilizzi di ThemeResource potrebbero essere visualizzati in una serie di valori dipendenti. Ad esempio, un valore Color usato da un elemento SolidColorBrush, anch'esso una risorsa con chiave, potrebbe usare un riferimento a ThemeResource. Tuttavia, qualsiasi proprietà dell'interfaccia utente che usa la risorsa SolidColorBrush con chiave userebbe anche un riferimento a ThemeResource, in modo che ogni proprietà di tipo Brush che abilita un valore dinamico cambi quando cambia un tema.

Nota{ThemeResource} e la valutazione delle risorse di runtime sul cambio di tema è supportato in Windows 8.1 XAML ma non in XAML per le app destinata a Windows 8.

Risorse di sistema

Alcune risorse tema fanno riferimento a valori di risorse di sistema come valore secondario sottostante. Una risorsa di sistema è un valore di risorsa speciale che non si trova nei dizionari risorse XAML. Questi valori si basano sul comportamento del supporto XAML di Windows Runtime per inoltrare valori dal sistema stesso e rappresentarli in un formato a cui può fare riferimento una risorsa XAML. Ad esempio, esiste una risorsa di sistema denominata "SystemColorButtonFaceColor" che rappresenta un colore RGB. Questo colore deriva dagli aspetti dei colori di sistema e dei temi che non sono solo specifici delle app di Windows Runtime e Windows Runtime.

Le risorse di sistema sono spesso i valori sottostanti per un tema a contrasto elevato. L'utente ha il controllo delle scelte di colore per il tema a contrasto elevato e l'utente effettua queste scelte usando funzionalità di sistema che non sono specifiche delle app di Windows Runtime. Facendo riferimento alle risorse di sistema come riferimenti a ThemeResource , il comportamento predefinito dei temi a contrasto elevato per le app di Windows Runtime può usare questi valori specifici del tema controllati dall'utente ed esposti dal sistema. Inoltre, i riferimenti sono ora contrassegnati per la rivalutazione se il sistema rileva una modifica del tema in fase di esecuzione.

Esempio di utilizzo di {ThemeResource}

Ecco un esempio di XAML tratto dai file generic.xaml e themeresources.xaml predefiniti per spiegare come usare ThemeResource. Si esaminerà un solo modello (Button predefinito) e si vedrà come vengono dichiarate due proprietà (Background e Foreground) per rispondere ai cambiamenti di tema.

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

Qui, le proprietà accettano un valore Brush e il riferimento alle risorse SolidColorBrush denominate ButtonBackgroundThemeBrush e ButtonForegroundThemeBrush vengono create usando ThemeResource.

Queste stesse proprietà vengono anche regolate da alcuni degli stati di visualizzazione per Button. In particolare, il colore di sfondo cambia quando si fa clic su un pulsante. Anche qui, le animazioni Background e Foreground nello storyboard dello stato di visualizzazione usano oggetti DiscreteObjectKeyFrame e riferimenti a pennelli con ThemeResource come valore frame chiave.

<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>

Ognuno di questi pennelli è definito in precedenza in generic.xaml: devono essere definiti prima dei modelli che li usano per evitare riferimenti in avanti XAML. Ecco queste definizioni per il dizionario dei temi "Predefinito".

    <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" />
...

Ognuno degli altri dizionari dei temi ha quindi definito questi pennelli, ad esempio:

        <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}" />

Qui il valore Color è un altro riferimento ThemeResource a una risorsa di sistema. Se si fa riferimento a una risorsa di sistema e si vuole che venga modificato in risposta a un cambiamento di tema, è consigliabile usare ThemeResource per eseguire il riferimento.

Comportamento di Windows 8

Windows 8 non supportava l'estensione di markup ThemeResource, che è disponibile a partire da Windows 8.1. Inoltre, Windows 8 non supportava il cambio dinamico delle risorse correlate al tema per un'app di Windows Runtime. L'app doveva essere riavviata per raccogliere il cambiamento di tema per i modelli e gli stili XAML. Poiché non si tratta di un'esperienza utente ottimale, è preferibile ricompilare le app per Windows 8.1 in modo che possano usare stili con utilizzi ThemeResource e possano cambiare temi in modo dinamico quando lo fa l'utente. Le app compilate per Windows 8 ma in esecuzione in Windows 8.1 continuano a usare il comportamento di Windows 8.

Supporto degli strumenti in fase di progettazione per l'estensione di markup {ThemeResource}

Microsoft Visual Studio 2013 può includere i possibili valori chiave negli elenchi a discesa di Microsoft IntelliSense quando si usa l'estensione di markup {ThemeResource} in una pagina XAML. Ad esempio, non appena si digita "{ThemeResource", vengono visualizzate le chiavi delle risorse del tema XAML.

Quando è presente una chiave di risorsa nell'ambito dell'utilizzo {ThemeResource}, la funzione Vai a definizione (F12) può risolvere quella risorsa e mostrare generic.xaml per la fase di progettazione, dove viene definita la risorsa del tema. Poiché le risorse del tema sono definite più volte (per tema) Vai a definizione consente di passare alla prima definizione trovata nel file, ovvero la definizione per Default. Se si desiderano altre definizioni, è possibile cercare il nome della chiave all'interno del file e trovare le definizioni degli altri temi.