Stili XAML

È possibile personalizzare l'aspetto delle app in molti modi con il framework XAML. Con gli stili si possono impostare le proprietà dei controlli e riusarle per creare controlli dall'aspetto uniforme.

WinUI e stili

A partire da WinUI 2.2, abbiamo utilizzato la libreria Windows UI Library (WinUI) per apportare nuovi aggiornamenti allo stile visivo dei nostri componenti UI. Se noti che l'interfaccia utente non si aggiorna agli stili più recenti, assicurati di aggiornare il pacchetto WinUI NuGet più recente.

A partire da WinUI 2.6, forniamo nuovi stili per la maggior parte dei controlli e un nuovo sistema di versioning che ti permette di tornare agli stili dei controlli precedenti se necessario. Ti invitiamo a utilizzare i nuovi stili, in quanto si adattano meglio alla direzione del design di Windows. Tuttavia, se il tuo scenario non può supportare i nuovi stili, le versioni precedenti sono ancora disponibili.

Puoi cambiare la versione dello stile impostando la proprietà ControlsResourcesVersion su XamlControlsResources che includi nel tuo Application.Resources quando usi la versione 2 di WinUI. ControlsResourcesVersion il valore predefinito è il valore dell'enum Version2.

Impostando questo valore a Version1 , XamlControlsResources caricherà le versioni di stile precedenti invece dei nuovi stili utilizzati dall'ultima versione di WinUI. La modifica di questa proprietà in fase di esecuzione non è supportata e la funzionalità di ricarica a caldo di VisualStudio non funzionerà; tuttavia, dopo aver ricostruito l'applicazione, vedrai gli stili del controllo cambiare.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

Stile di base

Usa gli stili per estrarre le impostazioni delle proprietà visive in risorse riutilizzabili. Ecco un esempio che mostra 3 pulsanti con uno stile che imposta le proprietà BorderBrush, BorderThickness e Foreground . Applicando uno stile, puoi far apparire i controlli allo stesso modo senza dover impostare le proprietà su ogni controllo separatamente.

Screenshot of three styled buttons arranged side by side.

Puoi definire uno stile in linea nello XAML di un controllo o come risorsa riutilizzabile. Definisci le risorse nel file XAML di una singola pagina, nel file App.xaml o in un file XAML separato del dizionario delle risorse. Un file XAML del dizionario delle risorse può essere condiviso tra le varie app e più di un dizionario delle risorse può essere unito in una singola app. Il luogo in cui viene definita la risorsa determina l'ambito in cui può essere utilizzata. Le risorse a livello di pagina sono disponibili solo nella pagina in cui sono state definite. Se le risorse con la stessa chiave sono definite sia in App.xaml che in una pagina, la risorsa nella pagina sostituisce quella in App.xaml. Se una risorsa è definita in un file di dizionario risorse separato, il suo ambito è determinato dai punti in cui si fa riferimento al dizionario risorse.

Nella definizione di Style è necessario un attributo TargetType e una collezione di uno o più elementi Setter . L'attributo TargetType è una stringa che specifica un tipo FrameworkElement a cui applicare lo stile. Il valore TargetType deve specificare un tipo derivato da FrameworkElementdefinito da Windows Runtime o un tipo personalizzato disponibile in un assembly di riferimento. Se cerchi di applicare uno stile a un controllo e il tipo del controllo non corrisponde all'attributo TargetType dello stile che stai cercando di applicare, si verifica un'eccezione.

Ogni elemento Setter richiede una proprietà e un valore . Queste impostazioni di proprietà indicano a quale proprietà del controllo si applica l'impostazione e il valore da impostare per quella proprietà. Puoi impostare il Setter.Value con la sintassi dell'attributo o dell'elemento di proprietà. Lo XAML qui riportato mostra lo stile applicato ai pulsanti mostrati in precedenza. In questo codice XAML i primi due elementi Setter usano la sintassi degli attributi, mentre l'ultimo Setter, per la proprietà BorderBrush, usa la sintassi degli elementi di proprietà. L'esempio non utilizza l'attributo x:Key , quindi lo stile viene applicato implicitamente ai pulsanti. L'applicazione degli stili in modo implicito o esplicito è spiegata nella prossima sezione.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

Applica uno stile implicito o esplicito

Se definisci uno stile come risorsa, ci sono due modi per applicarlo ai tuoi controlli:

Se uno stile contiene l'attributo x:Key, puoi applicarlo a un controllo solo impostando la proprietà Style del controllo sullo stile con chiave. Al contrario, uno stile senza attributo x:Key viene applicato automaticamente a tutti i controlli del suo tipo di destinazione che non hanno un'impostazione di stile esplicita.

Ecco due pulsanti che dimostrano gli stili impliciti ed espliciti.

implicitly and explicitly styled buttons.

In questo esempio il primo stile include un attributo x:Key e il tipo di destinazione è Button. La proprietà Style del primo pulsante è impostata su questa chiave, quindi questo stile viene applicato esplicitamente. Il secondo stile viene applicato implicitamente al secondo pulsante perché il suo tipo di destinazione è Button e lo stile non ha un attributo x:Key.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

Utilizza stili basati su

Per rendere gli stili più facili da mantenere e per ottimizzare il riutilizzo degli stili, puoi creare stili che ereditano da altri stili. Utilizza la proprietà BasedOn per creare stili ereditati. Gli stili che ereditano da altri stili devono essere indirizzati allo stesso tipo di controllo o a un controllo che deriva dal tipo indirizzato dallo stile di base. Se ad esempio la destinazione di uno stile di base è ContentControl, la destinazione degli stili basati su questo stile può essere ContentControl oppure tipi che derivano da ContentControl, come Button e ScrollViewer. Se un valore non è impostato nello stile basato, viene ereditato dallo stile di base. Per modificare un valore dello stile di base, lo stile basato su di esso lo sovrascrive. L'esempio seguente mostra un controllo Button e un controllo CheckBox con stili che ereditano dallo stesso stile di base.

styled buttons usign based-on styles.

Lo stile base si rivolge al ContentControl e imposta le proprietà Heighte Width . Gli stili basati su questo stile sono destinati a CheckBox e Button, che derivano da ContentControl. Gli stili basati impostano colori diversi per le proprietà BorderBrush e Foreground . (In genere non si mette un bordo intorno a un CheckBox . Lo facciamo qui per mostrare gli effetti dello stile)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Usa gli strumenti per lavorare facilmente con gli stili

Un modo veloce per applicare gli stili ai tuoi controlli è fare clic con il tasto destro del mouse su un controllo nella superficie di progettazione di Microsoft Visual Studio XAML e selezionare Edit Style o Edit Template (a seconda del controllo su cui stai facendo clic con il tasto destro del mouse). Puoi quindi applicare uno stile esistente selezionando Apply Resource o definire un nuovo stile selezionando Create Empty. Se crei uno stile vuoto, ti viene data la possibilità di definirlo nella pagina, nel file App.xaml o in un dizionario di risorse separato.

Stile leggero

L'override dei pennelli di sistema viene eseguito in genere a livello di app o di pagina e in entrambi i casi l'override del colore influisce su tutti i controlli che fanno riferimento al pennello. In XAML molti controlli possono fare riferimento allo stesso pennello di sistema.

Screenshot of two buttons: one in its rest state and one with lightweight Styling applied.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

Per stati come PointerOver (il mouse passa sopra il pulsante), PointerPressed (il pulsante è stato richiamato) o Disabled (il pulsante non è interattivo). Queste terminazioni vengono aggiunte ai nomi originali dello stile Lightweight: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, ecc. Modificando anche questi pennelli, ti assicurerai che i tuoi controlli siano colorati in modo coerente con il tema della tua applicazione.

Collocando questi override dei pennelli al livello App.Resources , si modificheranno tutti i pulsanti all'interno dell'intera applicazione, invece che in una singola pagina.

Stile per controllo

In altri casi, si desidera modificare un singolo controllo in una pagina solo per ottenere un certo aspetto, senza alterare altre versioni di quel controllo:

Screenshot of three styled buttons arranged stacked one on top of the other.

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

Questo avrebbe effetto solo su quella "Casella di controllo speciale" nella pagina in cui è presente quel controllo.

Controlli personalizzati

Quando costruisci i tuoi controlli personalizzati che possono essere visivamente e/o funzionalmente allineati con i nostri controlli integrati, prendi in considerazione l'utilizzo di risorse di stile implicito e di stile leggero per definire il tuo contenuto personalizzato. Puoi utilizzare le risorse direttamente o creare un nuovo alias per la risorsa.

Utilizzo diretto delle risorse di controllo

Ad esempio, se stai scrivendo un controllo che assomiglia a un pulsante, puoi fare in modo che il tuo controllo faccia riferimento direttamente alle risorse del pulsante, in questo modo:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

Aliasing delle risorse di controllo con nuovi nomi

In alternativa, se preferisci creare le tue risorse, devi assegnare un alias ai nomi personalizzati delle nostre risorse predefinite Lightweight styling.

Ad esempio, lo stile del tuo controllo personalizzato potrebbe avere delle definizioni di risorse speciali:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

Nel Dizionario delle risorse o nella definizione principale, devi collegare le risorse di stile Lightweight a quelle personalizzate:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

È necessario utilizzare un ThemeDictionary duplicato tre volte per gestire correttamente i tre diversi cambi di tema (Default, Light, HighContrast).

Attenzione

Se assegni una risorsa Lightweight styling a un nuovo alias e ridefinisci anche la risorsa Lightweight styling, la tua personalizzazione potrebbe non essere applicata se la ricerca delle risorse non avviene nell'ordine corretto. Ad esempio, se sovrascrivi ButtonBackground in un punto che viene cercato prima che venga trovato MyCustomControlBackground , la sovrascrittura verrebbe persa.

Evita il restyling dei controlli

La libreria Windows UI Library 2.2 o successiva include nuovi stili e modelli per i controlli WinUI e di sistema.

Il modo migliore per rimanere aggiornati con gli stili visivi più recenti è utilizzare l'ultimo pacchetto WinUI 2 ed evitare stili e modelli personalizzati (noti anche come re-templating). Gli stili sono ancora un modo comodo per applicare un insieme di valori in modo coerente tra i controlli della tua applicazione. Quando lo fai, assicurati di basarti sui nostri stili più recenti.

Per i controlli di sistema che utilizzano gli stili WinUI (spazio dei nomiWindows.UI.Xaml.Controls ), imposta BasedOn="{StaticResource Default<ControlName>Style}", dove <ControlName> è il nome del controllo. Ad esempio:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

Per i controlli WinUI 2 (spazio dei nomiMicrosoft.UI.Xaml.Controls ), lo stile predefinito è definito nei metadati, quindi ometti BasedOn.

Controlli derivati

Se derivi un controllo personalizzato da un controllo XAML esistente, non riceverà gli stili di WinUI 2 per impostazione predefinita. Per applicare gli stili di WinUI 2:

  • Crea un nuovo stile con il suo TargetType impostato sul tuo controllo personalizzato.
  • Basa lo stile sullo stile predefinito del controllo da cui deriva.

Uno scenario comune è quello di derivare un nuovo controllo da ContentDialog. Questo esempio mostra come creare un nuovo Stile che applica DefaultContentDialogStyle alla tua finestra di dialogo personalizzata.

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

La proprietà del modello

Un setter di stile può essere utilizzato per la proprietà Template di un controllo , e in effetti questo costituisce la maggior parte di uno stile XAML tipico e delle risorse XAML di un'applicazione. Questo aspetto è trattato in modo più dettagliato nell'argomento Modelli di controllo.