Modelli di controllo

Puoi personalizzare la struttura e il comportamento visivo di un controllo creando un modello di controllo nel framework XAML. I controlli hanno molte proprietà, come Background, Foreground, e FontFamily, che puoi impostare per specificare diversi aspetti dell'aspetto del controllo. Ma le modifiche che puoi apportare impostando queste proprietà sono limitate. Puoi specificare ulteriori personalizzazioni creando un modello utilizzando la classe ControlTemplate . Qui ti mostriamo come creare un ControlTemplate per personalizzare l'aspetto di un controllo CheckBox .

API importanti: Classe ControlTemplate, Proprietà Control.Template

Esempio di modello di controllo personalizzato

Per impostazione predefinita, un controllo CheckBox mette il suo contenuto (la stringa o l'oggetto accanto al CheckBox) a destra della casella di selezione e un segno di spunta indica che l'utente ha selezionato il CheckBox. Queste caratteristiche rappresentano la struttura visiva e il comportamento visivo di CheckBox.

Ecco un CheckBox che utilizza il ControlTemplate predefinito mostrato negli stati Unchecked, Checkede Indeterminate .

default checkbox template

Puoi modificare queste caratteristiche creando un ControlTemplate per il CheckBox. Ad esempio, se vuoi che il contenuto della casella di controllo sia sotto la casella di selezione e vuoi utilizzare una X per indicare che un utente ha selezionato la casella di controllo. Specifica queste caratteristiche nel ControlTemplate del CheckBox .

Per utilizzare un modello personalizzato con un controllo, assegna il modello ControlTemplate alla proprietà Template del controllo. Ecco un CheckBox che utilizza un ControlTemplate chiamato CheckBoxTemplate1. Nella prossima sezione mostreremo l'Extensible Application Markup Language (XAML) del ControlTemplate .

<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

Ecco come appare questo CheckBox negli stati Unchecked, Checkede Indeterminate dopo aver applicato il nostro modello.

custom checkbox template

Specifica la struttura visiva di un controllo

Quando crei un ControlTemplate , combini gli oggetti FrameworkElement per creare un singolo controllo. Un ControlTemplate deve avere solo un FrameworkElement come elemento radice. L'elemento radice di solito contiene altri oggetti FrameworkElement . La combinazione degli oggetti costituisce la struttura visiva del controllo.

Questo XAML crea un ControlTemplate per un CheckBox che specifica che il contenuto del controllo si trova sotto la casella di selezione. L'elemento radice è un Border. L'esempio specifica un Percorso per creare una X che indica che un utente ha selezionato la CheckBoxe una Ellisse che indica uno stato indeterminato. Nota che l'Opacità è impostata a 0 sul Percorso e sull'Ellisse in modo che per impostazione predefinita non appaia nessuno dei due.

TemplateBinding è un tipo speciale di binding che collega il valore di una proprietà in un modello di controllo a quello di un’altra proprietà esposta nel controllo basato su modelli. Il TemplateBinding può essere utilizzato solo all'interno di una definizione di ControlTemplate in XAML. Per altre informazioni, vedi Estensione di markup TemplateBinding.

Nota

A partire da Windows 10, versione 1809 (SDK 17763), puoi usare le estensioni di markup X:Bind nelle posizioni in cui usi TemplateBinding . Per altre informazioni, vedi Estensione di markup TemplateBinding.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Specifica il comportamento visivo di un controllo

Un comportamento visivo specifica l'aspetto di un controllo quando si trova in un determinato stato. Il controllo CheckBox ha 3 stati di controllo: Checked, Unchecked, e Indeterminate. Il valore della proprietà IsChecked determina lo stato della CheckBoxe il suo stato determina ciò che appare nella casella.

Questa tabella elenca i possibili valori di IsChecked, gli stati corrispondenti del CheckBox e l'aspetto del CheckBox .

IsChecked valore Stato della CheckBox Aspetto del CheckBox
true Checked Contiene una "X".
false Unchecked Vuoto.
Null Indeterminate Contiene un cerchio.

Puoi specificare l'aspetto di un controllo quando si trova in un determinato stato utilizzando gli oggetti VisualState . Un VisualState contiene un Setter o uno Storyboard che modifica l'aspetto degli elementi del ControlTemplate. Quando il controllo entra nello stato specificato dalla proprietà VisualState.Name , vengono applicate le modifiche della proprietà Setter o Storyboard . Quando il controllo esce dallo stato, le modifiche vengono rimosse. Si aggiungono gli oggetti VisualState agli oggetti VisualStateGroup . Si aggiungono oggetti VisualStateGroup alla proprietà VisualStateManager.VisualStateGroups attached, che si imposta sulla radice FrameworkElement del ControlTemplate.

Questo XAML mostra gli oggetti VisualState per gli stati Checked, Uncheckede Indeterminate . L'esempio imposta la proprietà VisualStateManager.VisualStateGroups allegata al Border, che è l'elemento radice del ControlTemplate. L'impostazione Checked per VisualState specifica che la proprietà Opacity dell'oggetto Path denominato CheckGlyph (vedi esempio precedente) è 1. L'impostazione Indeterminate per VisualState specifica che la proprietà Opacity dell'oggetto Ellipse denominato IndeterminateGlyph è 1. L'impostazione Unchecked per VisualState non ha Setter o Storyboard, pertanto il controllo CheckBox ritorna al suo aspetto predefinito.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                    <VisualState.Setters>
                        <Setter Target="CheckGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
                <VisualState x:Name="Unchecked"/>
                <VisualState x:Name="Indeterminate">
                    <VisualState.Setters>
                        <Setter Target="IndeterminateGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="IndeterminateGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Per capire meglio come funzionano gli oggetti VisualState considera cosa succede quando il CheckBox passa dallo stato Unchecked allo stato Checked , poi allo stato Indeterminate e infine allo stato Unchecked . Ecco le transizioni.

Transizione di stato Effetti Aspetto della casella di controllo quando la transizione è completata
Da Unchecked a Checked. Viene applicato il valore Setter di CheckedVisualState, quindi la proprietà Opacity di CheckGlyph è 1. Viene visualizzata una X.
Da Checked a Indeterminate. Viene applicato il valore Setter di IndeterminateVisualState, quindi la proprietà Opacity di IndeterminateGlyph è 1. Viene rimosso il valore Setter di CheckedVisualState, quindi la proprietà Opacity di CheckGlyph è 0. Viene visualizzato un cerchio.
Da Indeterminate a Unchecked. Viene rimosso il valore Setter di IndeterminateVisualState, quindi la proprietà Opacity di IndeterminateGlyph è 0. Non viene visualizzato nulla.

  Per maggiori informazioni su come creare stati visivi per i controlli, e in particolare su come utilizzare la classe Storyboard e i tipi di animazione, vedi Animazioni con storyboard per stati visivi.

Usa gli strumenti per lavorare facilmente con i temi

Un modo veloce per applicare i temi ai tuoi controlli è quello di fare clic con il tasto destro del mouse su un controllo nel Microsoft Visual Studio Document Outline e selezionare Edit Theme o Edit Style (a seconda del controllo su cui stai facendo clic con il tasto destro del mouse). Puoi quindi applicare un tema esistente selezionando Apply Resource o definirne uno nuovo selezionando Create Empty.

Controlli e accessibilità

Quando crei un nuovo modello per un controllo, oltre a modificare il comportamento e l'aspetto visivo del controllo, potresti anche cambiare il modo in cui il controllo si rappresenta ai framework di accessibilità. L'app di Windows supporta il framework di automazione interfaccia utente di Microsoft per l'accessibilità. Tutti i controlli predefiniti e i loro modelli supportano i tipi e i modelli di controllo UI Automation più comuni, adatti allo scopo e alla funzione del controllo. Questi tipi e schemi di controllo sono interpretati dai client di UI Automation, come le tecnologie assistive, e questo permette a un controllo di essere accessibile come parte di un'interfaccia utente accessibile più ampia.

Per separare la logica di controllo di base e anche per soddisfare alcuni dei requisiti architettonici dell'automazione dell'interfaccia utente, le classi di controllo includono il loro supporto all'accessibilità in una classe separata, un peer di automazione. I peer dell'automazione a volte hanno interazioni con i modelli di controllo perché i peer si aspettano che nei modelli siano presenti alcune parti denominate, in modo da rendere possibili funzionalità come l'abilitazione delle tecnologie assistive per richiamare le azioni dei pulsanti.

Quando crei un controllo personalizzato completamente nuovo, a volte vorrai creare anche un nuovo peer di automazione da abbinare ad esso. Per maggiori informazioni, vedi I colleghi dell'automazione personalizzata.

Per saperne di più sul modello predefinito di un controllo

Gli argomenti che documentano gli stili e i modelli per i controlli XAML mostrano estratti dello stesso XAML di partenza che vedresti se usassi le tecniche Edit Theme o Edit Style spiegate in precedenza. Ogni argomento elenca i nomi degli stati visivi, le risorse del tema utilizzate e l'intero XAML dello stile che contiene il modello. Gli argomenti possono essere una guida utile se hai già iniziato a modificare un modello e vuoi vedere come appariva il modello originale, oppure per verificare che il tuo nuovo modello abbia tutti gli stati visivi nominati richiesti.

Risorse a tema nei modelli di controllo

Per alcuni attributi negli esempi XAML, potresti aver notato dei riferimenti a risorse che utilizzano l'estensione di markup {ThemeResource}. Questa è una tecnica che permette a un singolo modello di controllo di utilizzare risorse che possono avere valori diversi a seconda del tema attivo. Questo è particolarmente importante per i pennelli e i colori, perché lo scopo principale dei temi è quello di permettere agli utenti di scegliere se vogliono un tema scuro, chiaro o ad alto contrasto applicato al sistema nel suo complesso. Le applicazioni che utilizzano il sistema di risorse XAML possono utilizzare un set di risorse appropriato per quel tema, in modo che le scelte del tema nell'interfaccia utente di un'applicazione riflettano la scelta del tema a livello di sistema dell'utente.

Scaricare il codice di esempio