Condividi tramite


Applicazione di stili e modelli

Aggiornamento: novembre 2007

L'applicazione di stili e modelli di Windows Presentation Foundation (WPF) fa riferimento a un insieme di funzionalità (stili, modelli, trigger e storyboard) che consentono ai progettisti di un'applicazione, un documento o un'interfaccia utente di creare effetti visivamente accattivanti e standardizzare un aspetto coerente per il prodotto. Nonostante gli autori o progettisti abbiano la possibilità di personalizzare l'aspetto per ogni singola applicazione, un modello stilistico sicuro è necessario per conservare e condividere l'aspetto tra più applicazioni e all'interno delle stesse. Windows Presentation Foundation (WPF) fornisce tale modello.

Un'altra funzionalità del modello stilistico WPF è la separazione della presentazione dalla logica. Ciò significa che i progettisti sono in grado di lavorare sull'aspetto di un'applicazione utilizzando soltanto XAML nello stesso momento in cui gli sviluppatori lavorano sulla logica di programmazione mediante C# o Visual Basic.

In questa sezione viene illustrata l'applicazione contenuta in Esempio di introduzione agli stili e ai modelli, dotata di due elementi TextBlock e un controllo ListBox associato a un elenco di immagini:

ListView con stile

La sezione è incentrata sull'utilizzo di stili e modelli per l'applicazione, mentre non è incluso alcun concetto relativo all'associazione dati. Per informazioni sull'associazione dati, vedere Cenni preliminari sull'associazione dati.

È inoltre importante conoscere le risorse, ovvero quegli elementi che consentono di riutilizzare stili e modelli. Per ulteriori informazioni sulle risorse, vedere Cenni preliminari sulle risorse.

Nel presente argomento sono contenute le seguenti sezioni.

  • Nozioni fondamentali sullo stile
  • Modelli di dati
  • Modelli di controlli
  • Trigger
  • Risorse e temi condivisi
  • Argomenti correlati

Nozioni fondamentali sullo stile

Un oggetto Style costituisce una valida soluzione per applicare un insieme di valori di proprietà a più elementi. Si considerino ad esempio i seguenti elementi TextBlock e il relativo aspetto predefinito:

<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

Schermata dell'esempio Styling

È possibile modificare l'aspetto predefinito impostando direttamente proprietà quali FontSize e FontFamily in ogni elemento TextBlock. Tuttavia, per fare in modo che gli elementi TextBlock condividano alcune proprietà, è possibile creare un oggetto Style nella sezione Resources del file XAML, come illustrato di seguito:

<Window.Resources>


...


<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
  <Setter Property="HorizontalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
  <Setter Property="FontSize" Value="14"/>
</Style>


...


</Window.Resources>

Quando si imposta TargetType per lo stile sul tipo TextBlock, lo stile viene applicato a tutti gli elementi TextBlock nella finestra.

Ora gli elementi TextBlock appaiono come segue:

Schermata dell'esempio Styling

Nella presente sezione sono contenute le seguenti sottosezioni.

  • Estensione degli stili
  • Relazione tra proprietà TargetType e attributo x:Key
  • Stili e risorse
  • Impostazione di stili a livello di codice
  • Associazioni, risorse dinamiche e gestori eventi

Estensione degli stili

Si supponga di volere che i due elementi TextBlock condividano alcuni valori di proprietà, ad esempio FontFamily e HorizontalAlignment centrato, ma anche che il testo "My Pictures" abbia alcune proprietà aggiuntive. A tale scopo è possibile creare un nuovo stile basato sul primo, come illustrato di seguito:

<Window.Resources>


...


<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
       TargetType="TextBlock"
       x:Key="TitleText">
  <Setter Property="FontSize" Value="26"/>
  <Setter Property="Foreground">
  <Setter.Value>
      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Offset="0.0" Color="#90DDDD" />
          <GradientStop Offset="1.0" Color="#5BFFFF" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
</Style>


...


</Window.Resources>

A questo stile viene attribuito un oggetto x:Key. Per applicare lo stile, impostare la proprietà Style di TextBlock sul valore x:Key, come illustrato di seguito:

<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

Ora lo stile di TextBlock ha un valore HorizontalAlignment equivalente a Center, un valore FontFamily equivalente a Comic Sans MS, un valore FontSize pari a 26 e un valore Foreground impostato sull'oggetto LinearGradientBrush illustrato nell'esempio. È stato quindi eseguito l'override del valore FontSize dello stile di base. In presenza di più Setter che impostano la stessa proprietà in un oggetto Style, l'ultimo Setter dichiarato ha la precedenza.

Di seguito viene illustrato come appaiono ora gli elementi TextBlock:

TextBlock con stile

Questo stile TitleText estende lo stile creato per il tipo TextBlock. È anche possibile estendere uno stile dotato di x:Key utilizzando il valore x:Key. Vedere in proposito l'esempio fornito per la proprietà BasedOn.

Relazione tra proprietà TargetType e attributo x:Key

Come illustrato nel primo esempio, se si imposta la proprietà TargetType in TextBlock senza assegnare un attributo x:Key allo stile, questo verrà applicato a tutti gli elementi TextBlock. In questo caso, x:Key viene implicitamente impostato su {x:Type TextBlock}. Ciò significa che se si imposta esplicitamente x:Key su un valore diverso da {x:Type TextBlock}, Style non viene applicato automaticamente a tutti gli elementi TextBlock. Al contrario, sarà necessario applicare lo stile agli elementi TextBlock in modo esplicito, utilizzando il valore x:Key. Se lo stile si trova nella sezione delle risorse e in esso non viene impostata la proprietà TargetType, allora è necessario fornire un attributo x:Key.

Oltre a fornire un valore predefinito per x:Key, la proprietà TargetType specifica il tipo al quale vengono applicate le proprietà del metodo di impostazione. Qualora non venga specificato TargetType, è necessario qualificare le proprietà negli oggetti Setter con un nome della classe, utilizzando la sintassi Property="ClassName.Property". Ad esempio, anziché impostare Property="FontSize", occorre impostare Property su "TextBlock.FontSize" o "Control.FontSize".

Si noti anche come molti controlli WPF siano costituiti da una combinazione di altri controlli WPF. Se si crea un stile da applicare a tutti i controlli di un tipo, è possibile che si ottengano risultati imprevisti. Se ad esempio si crea uno stile destinato al tipo TextBlock in un oggetto Window, lo stile verrà applicato a tutti i controlli TextBlock della finestra, anche se TextBlock appartiene a un altro controllo quale ad esempio ListBox.

Stili e risorse

È possibile utilizzare uno stile su qualsiasi elemento derivante da FrameworkElement o FrameworkContentElement. Il metodo più comune per dichiarare un stile consiste nella dichiarazione sotto forma di risorsa nella sezione Resources di un file XAML, come illustrato negli esempi precedenti. Essendo risorse, gli stili rispettano le stesse regole di ambito applicabili a tutte le risorse. Il percorso in cui uno stile viene dichiarato influisce sul percorso in cui lo stesso può essere applicato. Se ad esempio lo stile viene dichiarato nell'elemento radice del file XAML della definizione di applicazione, tale stile potrà essere utilizzato nell'intero ambito dell'applicazione. Se si crea un'applicazione per l'esplorazione e si dichiara lo stile in uno dei file XAML dell'applicazione, lo stile potrà essere utilizzato soltanto in quel file. Per ulteriori informazioni sulle regole di ambito per le risorse, vedere Cenni preliminari sulle risorse.

In aggiunta, è possibile trovare ulteriori informazioni su stili e risorse in Risorse e temi condivisi più avanti in questo argomento.

Impostazione di stili a livello di codice

Per assegnare un stile denominato a un elemento a livello di codice, ottenere lo stile dall'insieme di risorse e assegnarlo alla proprietà Style dell'elemento. Gli elementi in un insieme di risorse sono di tipo Object, pertanto sarà necessario eseguire il cast dello stile recuperato a un oggetto Style prima di assegnarlo alla proprietà Style. Ad esempio, per impostare lo stile TitleText definito su un oggetto TextBlock denominato textblock1, utilizzare il codice che segue:

textblock1.Style = (Style)(this.Resources["TitleText"]);

Una volta applicato uno stile, questo viene bloccato e non può essere in alcun modo modificato. Per modificare uno stile già applicato in modo dinamico, è necessario creare un nuovo stile che sostituisca quello esistente. Per ulteriori informazioni, vedere la proprietà IsSealed.

È possibile creare un oggetto che sceglie uno stile da applicare in base alla logica personalizzata. Vedere in proposito l'esempio fornito per la classe StyleSelector.

Associazioni, risorse dinamiche e gestori eventi

È possibile utilizzare la proprietà Setter.Value per specificare un'Associazione dell'estensione di markup o un'Estensione del markup DynamicResource. Per ulteriori informazioni, vedere gli esempi forniti per la proprietà Setter.Value.

Finora si è discusso unicamente dei metodi di impostazione utilizzati per impostare il valore della proprietà. In uno stile è possibile specificare anche i gestori eventi. Per ulteriori informazioni, vedere EventSetter.

Modelli di dati

Questa applicazione di esempio include un controllo ListBox associato a un elenco di foto:

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
         Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>

ListBox appare attualmente come riportato di seguito:

ListBox prima dell'applicazione del modello

Gran parte dei controlli dispongono di un contenuto, il quale spesso deriva dai dati di associazione. In questo esempio, i dati sono rappresentati dall'elenco di foto. In WPF si utilizza un oggetto DataTemplateper definire la rappresentazione visiva dei dati. Fondamentalmente, gli elementi collocati in DataTemplate determinano l'aspetto dei dati nell'applicazione di cui si esegue il rendering.

Nell'applicazione di esempio, ogni oggetto Photo personalizzato possiede una proprietà Source di tipo string che specifica il percorso del file dell'immagine. Attualmente, gli oggetti foto appaiono come percorsi di file.

Per far apparire le foto come immagini, è necessario creare un oggetto DataTemplate sotto forma di risorsa:

<Window.Resources>


...


<!--DataTemplate to display Photos as images
    instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
  <Border Margin="3">
    <Image Source="{Binding Source}"/>
  </Border>
</DataTemplate>


...


</Window.Resources>

La proprietà DataType è molto simile alla proprietà TargetType di Style. Se DataTemplate si trova nella sezione delle risorse, quando si specifica un tipo per la proprietà DataType senza assegnare un attributo x:Key, DataTemplate viene applicato ogni qualvolta appare il suddetto tipo. Resta sempre la possibilità di assegnare un attributo x:Key a DataTemplate, quindi impostarlo come StaticResource per le proprietà che accettano i tipi DataTemplate, ad esempio ItemTemplate o ContentTemplate.

Nell'esempio precedente DataTemplate stabilisce essenzialmente che, ogni qualvolta è presente un oggetto Photo, questo deve apparire come Image all'interno di un oggetto Border. Con questo DataTemplate, l'applicazione appare come riportato di seguito:

Foto

L'applicazione di un modello di dati consente di utilizzare altre funzionalità. Ad esempio, in caso di visualizzazione di dati dell'insieme contenenti altri insiemi mediante un tipo HeaderedItemsControl quale ad esempio Menu o TreeView, è possibile utilizzare HierarchicalDataTemplate. Un'altra funzionalità è DataTemplateSelector, che consente di scegliere un oggetto DataTemplate da utilizzare in base alla logica personalizzata. Per ulteriori informazioni, vedere Cenni preliminari sui modelli di dati, in cui vengono trattate più dettagliatamente le diverse funzionalità dei modelli di dati.

Modelli di controlli

Nella presente sezione sono contenute le seguenti sottosezioni.

  • Senza utilizzare ControlTemplate
  • Definizione di ControlTemplate
  • Creazione di ControlTemplate
  • Proprietà IsItemsHost
  • ItemsPresenter e ContentPresenter
  • TemplateBinding

Ora che le foto appaiono come immagini, si proceda con la modifica della visualizzazione da verticale a orizzontale. A tal proposito, occorre definire ListBox come orizzontale.

Senza utilizzare ControlTemplate

Innanzitutto è importante sottolineare come non sia necessario utilizzare ControlTemplate per ottenere ListBox orizzontale. ListBox possiede una proprietà ItemsPanel che consente di impostare un oggetto ItemsPanelTemplate, ovvero il modello che controlla il layout degli elementi di ListBox. È possibile creare semplicemente uno stile ListBox e impostare la proprietà ItemsPanel, come illustrato nell'esempio che segue:

<Style TargetType="ListBox">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"/>
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

Questo metodo funziona correttamente e consente di ottenere ListBox orizzontale. In questo esempio viene mostrato come, a seconda dello scenario, siano possibili opzioni diverse dalla sostituzione di ControlTemplate. Nel caso di questo esempio, per ottenere un oggetto ListBox orizzontale dotato di proprietà aggiuntive, ad esempio gli angoli arrotondati, sarà necessario utilizzare ControlTemplate di ListBox.

Prima di fornire un esempio in proposito, è importante spiegare il concetto di ControlTemplate.

Definizione di ControlTemplate

La maggior parte dei controlli possiede un aspetto e un comportamento. Si consideri ad esempio un pulsante: l'aspetto è l'area generata che è possibile premere, mentre il comportamento è l'evento Click generato in risposta a un clic.

Talvolta è possibile che un controllo fornisca il comportamento necessario ma non l'aspetto. Finora è stato illustrato come sia possibile utilizzare metodi di impostazione dello stile per impostare valori di proprietà che influiscono sull'aspetto di un controllo. Tuttavia, per modificare la struttura di un controllo o impostare valori di proprietà sui componenti che costituiscono un controllo, è necessario utilizzare ControlTemplate.

In WPF, l'oggetto ControlTemplate di un controllo serve a definirne l'aspetto. È possibile modificare la struttura e l'aspetto di un controllo mediante definizione di un nuovo oggetto ControlTemplate per tale controllo. In molti casi, questa procedura offre una flessibilità sufficiente da non richiedere la scrittura di controlli personalizzati. Se ControlTemplate non viene definito per il controllo, si ottiene il modello predefinito che corrisponde al tema del sistema, il quale conferisce al controllo Button l'aspetto predefinito.

È bene ricordare che, una volta creato un oggetto ControlTemplate per il controllo, l'intero ControlTemplate viene sostituito. Ad esempio, è possibile definire ControlTemplate per Button come illustrato di seguito.

Si noti che l'elemento ContentPresenter indica semplicemente la posizione in cui deve essere inserito Content dell'oggetto Button. I diversi componenti verranno trattati in una sezione successiva.

<Style TargetType="Button">
  <!--Set to true to not get any properties from the themes.-->
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse Fill="{TemplateBinding Background}"/>
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Applicando questa procedura, Button appare nella forma di un oggetto Ellipse:

Esempio di ControlTemplate del pulsante

Tenere presente che l'aspetto di Button nello stato attivo o durante la pressione fa parte dell'aspetto predefinito del pulsante che verrà sostituito. Pertanto, a seconda delle esigenze, è possibile che si debba indicare nella definizione quale deve essere l'aspetto del pulsante quando viene premuto. Per un esempio completo, vedere Esempio di ControlTemplate del controllo Button.

Per la creazione di ControlTemplate, il modo migliore per iniziare consiste nell'utilizzo degli Esempi di ControlTemplate. Per analizzare in dettaglio le parti che compongono un controllo, è possibile esaminare il file dei temi che si trova in Temi oppure utilizzare la funzionalità Show Visual Tree di XAMLPad, un'applicazione installata con Windows Software Development Kit (SDK).

Creazione di ControlTemplate

Per continuare con l'esempio, verrà ora creato un oggetto ControlTemplate che definisce un oggetto ListBox orizzontale caratterizzato da angoli arrotondati. Per sostituire ControlTemplate di un controllo, impostare la proprietà Template sul nuovo ControlTemplate.

<Style TargetType="ListBox">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBox">
        <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
          <ScrollViewer HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Questa procedura di impostazione della proprietà Template consente di ottenere lo stesso risultato ottenuto con l'impostazione di altre proprietà del controllo tramite Style: si utilizza Style come strumento che consente di impostare la proprietà Template. Ciò significa che un altro modo per impostare ControlTemplate consiste nell'impostare direttamente la proprietà Template nel controllo. Così facendo ControlTemplate viene creato nella sezione Resources, dotato di un oggetto x:Key, quindi utilizzato come risorsa statica. Per un esempio, vedere la proprietà Template.

Come si evince dal precedente esempio, la classe ControlTemplate possiede una proprietà TargetType simile alla proprietà TargetType della classe Style. Tuttavia, a differenza di Style e DataTemplate, gli oggetti ControlTemplate non possiedono la nozione di una chiave implicita. In altre parole, in caso di ControlTemplate autonomo con la proprietà TargetType impostata su un tipo, ControlTemplate non viene applicato automaticamente al suddetto tipo. Inoltre, la proprietà TargetType è obbligatoria per un oggetto ControlTemplate nel caso in cui la definizione del modello contenga un oggetto ContentPresenter.

Si provi a sperimentare ControlTemplate. Sostituire ad esempio StackPanel con WrapPanel, impostare la proprietà HorizontalScrollBarVisibility di ScrollViewer su Disabled, quindi impostare la proprietà Width di ListBox su 300. WrapPanel colloca gli elementi nella riga successiva soltanto quando lo spazio a disposizione nella prima riga si esaurisce. Se non si imposta la proprietà HorizontalScrollBarVisibility di ScrollViewer su Disabled, la prima riga non esaurisce lo spazio a disposizione poiché è possibile scorrerla fino alla fine. Di conseguenza, WrapPanel non esegue il wrapping degli elementi.

Proprietà IsItemsHost

In questo esempio, una proprietà importante da utilizzare è IsItemsHost. La proprietà IsItemsHost viene utilizzata per indicare la posizione in cui inserire gli elementi generati nel modello di un oggetto ItemsControl, ovvero controlli quali ListBox funzionanti con un elenco di elementi. Se si imposta la proprietà su true in StackPanel, tutti gli elementi aggiunti a ListBox vengono inseriti in StackPanel. Questa proprietà funziona solo con i tipi Panel.

ItemsPresenter e ContentPresenter

Tuttavia, quando si specifica un riquadro in ControlTemplate e lo si contrassegna come IsItemsHost in questo modo, ItemsPanel non può essere sostituito dall'utente del controllo senza utilizzare ControlTemplate. Pertanto, servirsi di questa procedura esclusivamente se si è certi di non voler sostituire il riquadro senza l'utilizzo di un modello. In alternativa, è possibile utilizzare l'elemento ItemsPresenter per indicare la posizione in cui gli elementi verranno inseriti, quindi specificare un oggetto ItemsPanelTemplate impostando la proprietà ItemsPanel. Nella pagina relativa a ItemsPanelTemplate è presente un esempio che illustra la procedura. Per un altro esempio in cui viene utilizzato ItemsPresenter, vedere Esempio di ControlTemplate del controllo TreeView.

In caso di creazione di un modello per un oggetto ContentControl quale ad esempio Button, l'elemento corrispondente è ContentPresenter. In modo analogo, l'elemento viene collocato in ControlTemplate del tipo ContentControl per indicare la posizione in cui visualizzare il contenuto, come illustrato nell'esempio riportato nella sezione Definizione di ControlTemplate. Per altri esempi, vedere Esempio di ControlTemplate del controllo Label e Esempio di ControlTemplate del controllo ListBoxItem.

TemplateBinding

Importante da notare nell'esempio precedente è anche il valore Background impostato su {TemplateBinding ListBox.Background}. Ciò indica semplicemente che il valore Background di Border deve essere sincronizzato con il valore Background impostato in ListBox. Un oggetto TemplateBinding è simile a un oggetto Binding. Di fatto, TemplateBinding è più efficiente ma meno funzionale di Binding. Utilizzare TemplateBinding equivale a utilizzare Binding con la proprietà Source impostata su RelativeSource.TemplatedParent.

Utilizzare TemplateBinding in ControlTemplate per consentire all'utente del controllo di controllare i valori di determinate proprietà. TemplateBinding è un'estensione di markup rappresentata dalla classe TemplateBindingExtension.

DataTemplate e ControlTemplate sono simili per il fatto che i rispettivi contenuti diventano la visualizzazione di un oggetto. Con la definizione di ControlTemplate di ListBox, l'applicazione ora appare come riportato di seguito:

Schermata dell'esempio Styling

Trigger

Style, ControlTemplate e DataTemplate possiedono tutti una proprietà Triggers che può contenere un insieme di trigger. Un trigger consente di impostare proprietà o avviare azioni quali ad esempio un'animazione quando un valore di proprietà viene modificato oppure quando viene generato un evento.

Nella presente sezione sono contenute le seguenti sottosezioni.

  • Trigger di proprietà
  • EventTrigger e Storyboard
  • MultiTrigger, DataTrigger e MultiDataTrigger

Trigger di proprietà

Per illustrare l'utilizzo dei trigger per l'impostazione di proprietà, ogni ListBoxItem verrà reso parzialmente trasparente a meno che non sia selezionato.

Il seguente stile imposta il valore Opacity di un oggetto ListBoxItem su 0.5. Quando la proprietà IsSelected è true, invece, Opacity è impostato su 1.0:

<Style TargetType="ListBoxItem">
  <Setter Property="Opacity" Value="0.5" />
  <Setter Property="MaxHeight" Value="75" />
  <Style.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Setter Property="Opacity" Value="1.0" />
    </Trigger>


...


  </Style.Triggers>
</Style>

In questo esempio viene utilizzato un oggetto Trigger per impostare un valore di proprietà, ma è bene ricordare che la classe Trigger possiede anche le proprietà EnterActions e ExitActions che consentono a un trigger di eseguire determinate azioni.

Si noti anche che la proprietà MaxHeight di ListBoxItem è stata impostata su 75. Nella schermata che segue, il terzo elemento è quello selezionato:

ListView con stile

EventTrigger e Storyboard

Si è detto finora che un oggetto Trigger imposta valori di proprietà o esegue azioni in base al valore di una proprietà. Un altro tipo di trigger è EventTrigger, il quale avvia una serie di azioni in base all'occorrenza di un evento. Ad esempio, gli oggetti EventTrigger seguenti specificano che quando il puntatore del mouse entra in ListBoxItem, la proprietà MaxHeight assume un valore pari a 90 per un intervallo di 0.2 secondi. Quando il mouse si sposta dall'elemento, la proprietà ritorna al valore originale in 1 secondo. Non è necessario specificare un valore To per l'animazione MouseLeave. Questo perché l'animazione è in grado di tenere traccia del valore originale.

<EventTrigger RoutedEvent="Mouse.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:0.2"
          Storyboard.TargetProperty="MaxHeight"
          To="90"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:1"
          Storyboard.TargetProperty="MaxHeight"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

Per ulteriori informazioni, vedere Cenni preliminari sugli storyboard.

Nella schermata che segue, il mouse punta al terzo elemento:

Schermata dell'esempio Styling

MultiTrigger, DataTrigger e MultiDataTrigger

Oltre a Trigger e EventTrigger, esistono altri tipi di trigger. MultiTrigger consente di impostare valori di proprietà in base a più condizioni. DataTrigger e MultiDataTrigger vengono invece utilizzati quando la proprietà della condizione è associata a dati.

Per l'esempio completo illustrato in questo argomento, vedere Esempio di introduzione agli stili e ai modelli.

Risorse e temi condivisi

Un'applicazione Windows Presentation Foundation (WPF) tipica può disporre di più risorse dell'interfaccia utente applicate nell'intero ambito dell'applicazione. Nel complesso, questo insieme di risorse può essere considerato il tema dell'applicazione. Windows Presentation Foundation (WPF) fornisce un supporto per l'assemblaggio delle risorse dell'interfaccia utente sotto forma di tema mediante un dizionario risorse incapsulato come classe ResourceDictionary.

I temi Windows Presentation Foundation (WPF) vengono definiti utilizzando il meccanismo di applicazione di stili e modelli esposto da Windows Presentation Foundation (WPF) per la personalizzazione degli oggetti visivi di un elemento.

Le risorse dei temi Windows Presentation Foundation (WPF) vengono archiviate in dizionari risorse incorporati. Questi dizionari devono essere incorporati all'interno di un assembly firmato e possono essere incorporati nello stesso assembly del codice o in un assembly side-by-side. Nel caso di PresentationFramework.dll, l'assembly contenente i controlli Windows Presentation Foundation (WPF), le risorse del tema sono contenute in una serie di assembly side-by-side.

Il tema è in assoluto l'ultimo posto in cui cercare lo stile di un elemento. In genere, la ricerca inizia risalendo la struttura ad albero dell'elemento in cerca di una risorsa appropriata, prosegue quindi nell'insieme delle risorse dell'applicazione, per poi terminare con una query al sistema. In questo modo gli autori dell'applicazione possono ridefinire lo stile per qualsiasi oggetto a livello di struttura ad albero o di applicazione prima di arrivare al tema.

È possibile definire i dizionari risorse come singoli file che consentono di riutilizzare un tema all'interno di più applicazioni. È anche possibile creare temi scambiabili definendo più dizionari risorse che forniscono gli stessi tipi di risorse ma con valori diversi. La ridefinizione di questi stili o di altre risorse a livello di applicazione è l'approccio consigliato per definire l'interfaccia di un'applicazione.

Per condividere un insieme di risorse, inclusi stili e modelli, tra diverse applicazioni è possibile creare un file XAML e definire un oggetto ResourceDictionary. Si osservi ad esempio la schermata che segue, in cui viene illustrato parte dell'Esempio di applicazione di stili con ControlTemplate:

Esempi di modelli di controlli

Osservando i file XAML nell'esempio, si noterà che tutti possiedono il seguente codice:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

Si tratta della condivisione di shared.xaml, che definisce un oggetto ResourceDictionary contenente un insieme di risorse di stile e riempimento in grado di conferire un aspetto coerente ai controlli nell'esempio.

Per ulteriori informazioni, vedere Dizionari risorse uniti.

Per la creazione di un tema per il controllo personalizzato, consultare la sezione Libreria di controlli esterna contenuta in Cenni preliminari sulla modifica di controlli.

Vedere anche

Attività

Procedura: trovare elementi generati da un oggetto ControlTemplate

Procedura: trovare elementi generati da un oggetto DataTemplate

Demo Photo Store

Concetti

URI di tipo pack in Windows Presentation Foundation

Altre risorse

Temi