Condividi tramite


Risorse del tema XAML

Le risorse del tema in XAML sono un set di risorse che applicano valori diversi a seconda del tema di sistema attivo. Sono disponibili 3 temi supportati dal framework XAML: "Light", "Dark" e "HighContrast".

Prerequisiti: in questo argomento si presuppone che siano presenti riferimenti a ResourceDictionary e risorse XAML.

Risorse del tema v. Risorse statiche

Esistono due estensioni di markup XAML che possono fare riferimento a una risorsa XAML da un dizionario risorse XAML esistente: estensione di markup {StaticResource} e estensione di markup {ThemeResource}.

La valutazione di un'estensione di markup {ThemeResource} si verifica quando l'app viene caricata e successivamente ogni volta che il tema cambia in fase di esecuzione. Questo è in genere il risultato della modifica delle impostazioni del dispositivo da parte dell'utente o da una modifica a livello di codice all'interno dell'app che modifica il tema corrente.

Al contrario, un'estensione di markup {StaticResource} viene valutata solo quando il codice XAML viene caricato per la prima volta dall'app. Non viene aggiornato. È simile a una ricerca e sostituzione nel codice XAML con il valore di runtime effettivo all'avvio dell'app.

Risorse del tema nella struttura del dizionario risorse

Ogni risorsa del tema fa parte del file XAML themeresources.xaml. Ai fini della progettazione, themeresources.xaml è disponibile nella cartella \(Programmi)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic from a Windows Software Development Kit (SDK). I dizionari risorse in themeresources.xaml vengono riprodotti anche in generic.xaml nella stessa directory.

Windows Runtime non usa questi file fisici per la ricerca in fase di esecuzione. Ecco perché si trovano specificamente in una cartella DesignTime e non vengono copiati nelle app per impostazione predefinita. Questi dizionari di risorse esistono invece in memoria come parte di Windows Runtime stesso e i riferimenti alle risorse XAML dell'app alle risorse del tema (o alle risorse di sistema) vengono risolti in fase di esecuzione.

Linee guida per le risorse del tema personalizzate

Seguire queste linee guida quando si definiscono e si usano risorse del tema personalizzate:

Attenzione

Se non segui queste linee guida, potresti vedere comportamenti imprevisti correlati ai temi nella tua app. Per altre info, vedi la sezione Risoluzione dei problemi relativi alle risorse del tema .

La rampa di colori XAML e i pennelli dipendenti dal tema

Il set combinato di colori per i temi "Light", "Dark" e "HighContrast" costituiscono la rampa di colori di Windows in XAML. Se vuoi modificare i temi di sistema o applicare un tema ai tuoi elementi XAML, è importante comprendere come sono strutturate le risorse colore.

Per altre informazioni su come applicare il colore nella tua app di Windows, vedi Colore nelle app di Windows.

Colori del tema chiaro e scuro

Il framework XAML fornisce un set di risorse Color denominate con valori personalizzati per i temi "Chiaro" e "Scuro". Per WinUI 2, le risorse del tema vengono definite nel file Xaml delle risorse del tema comuni. I nomi dei colori sono molto descrittivi dell'utilizzo previsto e c'è una risorsa SolidColorBrush corrispondente per ogni risorsa Color.

Suggerimento

Per una panoramica visiva di questi colori, vedi l'app Raccolta WinUI 3: Colors

L'app Raccolta WinUI 3 include esempi interattivi della maggior parte dei controlli, delle funzionalità e delle funzionalità winUI 3. Ottenere l'app da Microsoft Store o ottenere il codice sorgente in GitHub

Colori dei temi a contrasto del sistema Windows

Oltre al set di risorse fornito dal framework XAML, è disponibile un set di valori di colore derivati dalla tavolozza del sistema Windows. Questi colori non sono specifici per le app di Windows Runtime o Windows. Tuttavia, molte delle risorse pennello XAML utilizzano questi colori quando il sistema è operativo (e l'app è in esecuzione) usando il tema "HighContrast". Il framework XAML fornisce questi colori a livello di sistema come risorse con chiave. Le chiavi seguono il formato di denominazione: SystemColor[name]Color.

Per altre informazioni sul supporto dei temi di contrasto, vedere Temi a contrasto.

Colore principale del sistema

Oltre ai colori del tema a contrasto di sistema, il colore principale del sistema viene fornito come risorsa colore speciale usando la chiave SystemAccentColor. In fase di esecuzione, questa risorsa ottiene il colore specificato dall'utente come colore principale nelle impostazioni di personalizzazione di Windows.

Annotazioni

Sebbene sia possibile eseguire l'override delle risorse colore di sistema, è consigliabile rispettare le scelte di colore dell'utente, soprattutto per le impostazioni del tema a contrasto.

Pennelli dipendenti dal tema

Le risorse colore illustrate nelle sezioni precedenti vengono usate per impostare la proprietà Color delle risorse SolidColorBrush nei dizionari risorse dei temi di sistema. Le risorse pennello vengono usate per applicare il colore agli elementi XAML.

Si esaminerà ora come viene determinato il valore del colore per questo pennello in fase di esecuzione. Nei dizionari risorse "Light" e "Dark" questo pennello è definito come segue:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{StaticResource TextFillColorPrimary}"/>

Nel dizionario risorse "HighContrast" questo pennello è definito come segue:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{ThemeResource SystemColorWindowTextColor}"/>

Quando questo pennello viene applicato a un elemento XAML, il colore viene determinato in fase di esecuzione dal tema corrente, come illustrato in questa tabella.

Tema Risorsa colore Valore di runtime
Light TextFillColorPrimary #E4000000
Oscuro TextFillColorPrimary #FFFFFFFF
HighContrast SystemColorWindowTextColor Colore specificato nelle impostazioni per Text.

Rampa del tipo XAML

Il file themeresources.xaml definisce diverse risorse che definiscono uno stile che puoi applicare ai contenitori di testo nell'interfaccia utente, in particolare per TextBlock o RichTextBlock. Questi non sono gli stili impliciti predefiniti. Vengono forniti per semplificare la creazione di definizioni dell'interfaccia utente XAML corrispondenti alla rampa di tipi di Windows documentata in Linee guida per i tipi di carattere.

Questi stili sono per gli attributi di testo che si desidera applicare all'intero contenitore di testo. Se si desidera applicare stili solo alle sezioni del testo, impostare attributi sugli elementi di testo all'interno del contenitore, ad esempio in un oggetto Run in TextBlock.Inlines o in un paragraph in RichTextBlock.Blocks.

Gli stili hanno un aspetto simile al seguente quando vengono applicati a un controllo TextBlock:

stili blocco di testo

Stile Weight Misura
Didascalia Regolare 12
Corpo Regolare 14
Corpo forte Semibold 14
Corpo grande Regolare 18
Sottotitolo Semibold 20
Titolo Semibold 28
Titolo grande Semibold 40
Display Semibold 68
<TextBlock Text="Caption" Style="{StaticResource CaptionTextBlockStyle}"/>
<TextBlock Text="Body" Style="{StaticResource BodyTextBlockStyle}"/>
<TextBlock Text="Body Strong" Style="{StaticResource BodyStrongTextBlockStyle}"/>
<TextBlock Text="Body Large" Style="{StaticResource BodyLargeTextBlockStyle}"/>
<TextBlock Text="Subtitle" Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Title" Style="{StaticResource TitleTextBlockStyle}"/>
<TextBlock Text="Title Large" Style="{StaticResource TitleLargeTextBlockStyle}"/>
<TextBlock Text="Display" Style="{StaticResource DisplayTextBlockStyle}"/>

Per indicazioni su come usare la rampa dei tipi di Windows nella tua app, vedi Tipografia nelle app di Windows.

Per informazioni dettagliate sugli stili XAML, vedere WinUI in GitHub:

Suggerimento

Per una panoramica visiva di questi stili, vedi l'app Raccolta WinUI 3: Tipografia

BaseRichTextBlockStyle

TargetType: RichTextBlock

Fornisce le proprietà comuni per tutti gli altri stili di contenitore RichTextBlock .

<!-- Usage -->
<RichTextBlock Style="{StaticResource BaseRichTextBlockStyle}">
    <Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->
<Style x:Key="BaseRichTextBlockStyle" TargetType="RichTextBlock">
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontWeight" Value="SemiBold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="TextTrimming" Value="None"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="LineStackingStrategy" Value="MaxHeight"/>
    <Setter Property="TextLineBounds" Value="Full"/>
    <Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

BodyRichTextBlockStyle

<!-- Usage -->
<RichTextBlock Style="{StaticResource BodyRichTextBlockStyle}">
    <Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->
<Style x:Key="BodyRichTextBlockStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaseRichTextBlockStyle}">
    <Setter Property="FontWeight" Value="Normal"/>
</Style>

Nota: gli stili RichTextBlock non hanno tutti gli stili di rampa di testo che TextBlock esegue, principalmente perché il modello a oggetti documento basato su blocchi per RichTextBlock semplifica l'impostazione degli attributi sui singoli elementi di testo. Inoltre, l'impostazione di TextBlock.Text tramite la proprietà del contenuto XAML introduce una situazione in cui non esiste alcun elemento di testo da applicare allo stile e pertanto devi applicare uno stile al contenitore. Questo non è un problema per RichTextBlock perché il relativo contenuto di testo deve sempre trovarsi in elementi di testo specifici come Paragraph, dove è possibile applicare stili XAML per intestazione di pagina, sottotitolo di pagina e definizioni di rampa di testo simili.

Stili denominati vari

È disponibile un set aggiuntivo di definizioni di stile con chiave che è possibile applicare allo stile di un pulsante in modo diverso rispetto al relativo stile implicito predefinito.

TargetType: Pulsante

Questo stile fornisce un modello completo per un pulsante che può essere il pulsante Indietro di spostamento per un'app di spostamento. Le dimensioni predefinite sono 40 x 40 pixel. Per personalizzare lo stile, è possibile impostare in modo esplicito altezza, larghezza, fontsize e altre proprietà sul pulsante oppure creare uno stile derivato usando BasedOn.

Ecco un pulsante con la risorsa NavigationBackButtonNormalStyle applicata.

<Button Style="{StaticResource NavigationBackButtonNormalStyle}" />

Avrà l'aspetto seguente:

Pulsante con lo stile di un pulsante Indietro

TargetType: Pulsante

Questo stile fornisce un modello completo per un pulsante che può essere il pulsante Indietro di spostamento per un'app di spostamento. È simile a NavigationBackButtonNormalStyle, ma le sue dimensioni sono 30 x 30 pixel.

Ecco un pulsante con la risorsa NavigationBackButtonSmallStyle applicata.

<Button Style="{StaticResource NavigationBackButtonSmallStyle}" />

Risoluzione dei problemi relativi alle risorse del tema

Se non segui le linee guida per l'uso delle risorse del tema, potresti vedere comportamenti imprevisti correlati ai temi nella tua app.

Ad esempio, quando si apre un riquadro a comparsa con tema chiaro, le parti dell'app a tema scuro cambiano anche come se fossero nel tema chiaro. In alternativa, se si passa a una pagina con tema chiaro e quindi si torna indietro, la pagina originale con tema scuro (o parti di esso) sembra ora come se fosse nel tema chiaro.

In genere, questi tipi di problemi si verificano quando fornisci un tema "predefinito" e un tema "HighContrast" per supportare scenari a contrasto elevato e quindi usi temi "Chiaro" e "Scuro" in diverse parti dell'app.

Si consideri ad esempio questa definizione del dizionario dei temi:

<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Intuitivamente, l'aspetto è corretto. Vuoi modificare il colore a myBrush cui punta quando è a contrasto elevato, ma quando non è a contrasto elevato, fai affidamento sull'estensione di markup {ThemeResource} per assicurarti che myBrush punti al colore corretto per il tema. Se l'app non ha mai FrameworkElement.RequestedTheme impostato sugli elementi all'interno della struttura ad albero visuale, questo funzionerà in genere come previsto. Tuttavia, si verificano problemi nell'app non appena si inizia a rimettere in tema parti diverse della struttura ad albero visuale.

Il problema si verifica perché i pennelli sono risorse condivise, a differenza della maggior parte degli altri tipi XAML. Se sono presenti 2 elementi in sottoalberi XAML con temi diversi che fanno riferimento alla stessa risorsa pennello, poiché il framework guida ogni sottoalbero per aggiornare le espressioni di estensione di markup {ThemeResource} , le modifiche alla risorsa pennello condiviso vengono riflesse nell'altro sottoalbero, che non è il risultato previsto.

Per risolvere questo problema, sostituire il dizionario "Default" con dizionari di temi separati per i temi "Light" e "Dark" oltre a "HighContrast":

<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Tuttavia, i problemi si verificano ancora se a una di queste risorse viene fatto riferimento in proprietà ereditate come Foreground. Il modello di controllo personalizzato potrebbe specificare il colore di primo piano di un elemento usando l'estensione di markup {ThemeResource}, ma quando il framework propaga il valore ereditato agli elementi figlio, fornisce un riferimento diretto alla risorsa risolta dall'espressione di estensione di markup {ThemeResource}. Ciò causa problemi quando il framework elabora le modifiche del tema durante l'esecuzione della struttura ad albero visuale del controllo. Rivaluta l'espressione di estensione di markup {ThemeResource} per ottenere una nuova risorsa pennello, ma non propaga ancora questo riferimento agli elementi figlio del controllo; ciò si verifica in un secondo momento, ad esempio durante il passaggio successivo della misura.

Di conseguenza, dopo aver camminato la struttura ad albero visuale del controllo in risposta a una modifica del tema, il framework guida gli elementi figlio e aggiorna le espressioni di estensione di markup {ThemeResource} impostate su di essi o sugli oggetti impostati sulle relative proprietà. Questo è il luogo in cui si verifica il problema; il framework illustra la risorsa pennello e, poiché specifica il colore usando un'estensione di markup {ThemeResource}, viene rivalutata.

A questo punto, il framework sembra aver inquinato il dizionario dei temi perché ora ha una risorsa da un dizionario che ha il colore impostato da un altro dizionario.

Per risolvere il problema, usare l'estensione di markup {StaticResource} anziché l'estensione di markup {ThemeResource}. Con le linee guida applicate, i dizionari dei temi hanno un aspetto simile al seguente:

<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
      <SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
      <SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Si noti che l'estensione di markup {ThemeResource} viene ancora usata nel dizionario "HighContrast" anziché nell'estensione di markup {StaticResource}. Questa situazione rientra nell'eccezione specificata in precedenza nelle linee guida. La maggior parte dei valori del pennello usati per il tema "HighContrast" usa scelte di colore controllate a livello globale dal sistema, ma esposte a XAML come risorsa denominata appositamente (quelle con prefisso "SystemColor" nel nome). Il sistema consente all'utente di impostare i colori specifici che devono essere usati per le impostazioni del tema di contrasto tramite Il Centro accessibilità. Tali scelte di colore vengono applicate alle risorse con nome specifico. Il framework XAML usa lo stesso evento modificato del tema per aggiornare anche questi pennelli quando rileva che sono stati modificati a livello di sistema. Ecco perché qui viene usata l'estensione di markup {ThemeResource}.