Application d'un style et création de modèles

Mise à jour : novembre 2007

La création de modèles et l'application d'un style Windows Presentation Foundation (WPF) désignent une suite de fonctions (styles, modèles, déclencheurs et tables de montage séquentiel) qui permettent aux concepteurs d'une application, d'un document ou d'une interface utilisateur (UI) de créer des effets visuellement percutants et de standardiser une apparence homogène de leur produit. Bien qu'un auteur ou un concepteur puisse largement personnaliser l'apparence de chaque application, l'application d'un style particulier et la création d'un modèle distinct sont nécessaires pour permettre la maintenance et le partage de l'apparence au sein d'applications et entre des applications. Windows Presentation Foundation (WPF) fournit à ce modèle.

Une autre fonction du modèle de style WPF consiste en la séparation de la présentation et de la logique. Autrement dit, les concepteurs peuvent travailler sur l'apparence d'une application à l'aide de XAML seulement, pendant que les développeurs travaillent sur la logique de programmation à l'aide de C# ou Visual Basic.

Cette vue d'ensemble présente l'application Introduction aux styles et aux modèles, exemple, qui comporte deux éléments TextBlock et un contrôle ListBox lié à une liste d'images :

Vue de la liste mise en forme avec des styles

Cette vue d'ensemble s'intéresse principalement aux aspects de l'application liés à la définition d'un style et à la création de modèles, et n'aborde pas du tout la liaison de données. Pour plus d'informations sur la liaison de données, consultez Vue d'ensemble de la liaison de données.

En outre, il est important de comprendre ce que sont les ressources, puisque ce sont elles qui permettent la réutilisation des styles et des modèles. Pour plus d'informations sur les ressources, consultez Vue d'ensemble des ressources.

Cette rubrique comprend les sections suivantes.

  • Notions de base relatives aux styles
  • Modèles de données
  • Modèles de contrôle
  • Déclencheurs
  • Ressources partagées et thèmes
  • Rubriques connexes

Notions de base relatives aux styles

Vous pouvez considérer un Style comme un moyen pratique d'appliquer un ensemble de valeurs de propriétés à plusieurs éléments. Prenons, par exemple, les éléments TextBlock suivants et leur apparence par défaut :

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

Capture d'écran : exemple de styles

Vous pouvez modifier leur apparence par défaut en définissant des propriétés telles que FontSize et FontFamily directement sur chaque élément TextBlock. Toutefois, si vous souhaitez que vos éléments TextBlock partagent quelques propriétés, vous pouvez créer un Style dans la section Resources de votre fichier XAML, comme illustré ici :

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

Lorsque vous affectez au TargetType de votre style le type TextBlock, ce style est appliqué à tous les éléments TextBlock qui se trouvent dans la fenêtre.

Les éléments TextBlock apparaissent désormais comme suit :

Capture d'écran : exemple de styles

Cette section comprend les sous-sections suivantes.

  • Extension de styles
  • Relation de la propriété TargetType et de l'attribut x:Key
  • Styles et ressources
  • Définition de styles par programme
  • Liaisons, ressources dynamiques et gestionnaires d'événements

Extension de styles

Il est possible que vous souhaitiez que vos deux éléments TextBlock partagent quelques valeurs de propriété, telles que le FontFamily et le HorizontalAlignment centré, mais vous pouvez également souhaiter que le texte "Mes images" ait quelques propriétés supplémentaires. Pour ce faire, vous pouvez créer un style sur la base du premier style, comme illustré ici :

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

Notez qu'un x:Key est attribué au style précité. Pour appliquer le style, vous affectez la valeur x:Key à la propriété Style dans votre TextBlock, comme illustré ici :

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

La propriété HorizontalAlignment de ce style TextBlock a désormais la valeur Center ; la propriété FontFamily a la valeur Comic Sans MS ; la propriété FontSize a la valeur 26 ; et enfin, la propriété Foreground a la valeur LinearGradientBrush indiquée dans l'exemple. Notez que nous avons remplacé la valeur FontSize du style de base. Si plusieurs Setter définissent la même propriété dans un Style, le dernier Setter déclaré prime.

Voici à présent comment se présentent les éléments TextBlock :

TextBlocks mis en forme avec des styles

Ce style TitleText étend le style créé pour le type TextBlock. Vous pouvez également étendre un style qui a un x:Key en utilisant la valeur x:Key. Consultez l'exemple indiqué pour le BasedOn.

Relation de la propriété TargetType et de l'attribut x:Key

Comme indiqué dans le premier exemple, affecter à la propriété TargetType la valeur TextBlock sans assigner un x:Key au style entraîne l'application du style à tous les éléments TextBlock. Dans ce cas, x:Key a implicitement la valeur {x:Type TextBlock}. En d'autres termes, si vous affectez explicitement à x:Key une valeur autre que {x:Type TextBlock}, le Style n'est pas appliqué automatiquement à tous les éléments TextBlock. Au lieu de cela, vous devez appliquer explicitement le style (en utilisant la valeur x:Key) aux éléments TextBlock. Si votre style se trouve dans la section des ressources et vous ne définissez pas la propriété TargetType dans votre style, vous devez alors indiquer un x:Key.

Outre l'indication d'une valeur par défaut pour x:Key, la propriété TargetType spécifie le type auquel s'appliquent les propriétés d'accesseur Set. Si vous ne spécifiez pas de TargetType, vous devez qualifier les propriétés dans vos objets Setter avec un nom de classe, à l'aide de la syntaxe Property="ClassName.Property". Par exemple, au lieu de définir Property="FontSize", vous devez affecter à Property la valeur "TextBlock.FontSize" ou "Control.FontSize".

Notez également que de nombreux contrôles WPF consistent en une combinaison d'autres contrôles WPF. Si vous créez un style qui s'applique à tous les contrôles d'un type, vous risquez d'obtenir des résultats inattendus. Par exemple, si vous créez un style qui cible le type TextBlock dans un Window, le style est appliqué à tous les contrôles TextBlock qui se trouvent dans la fenêtre, y compris si le TextBlock fait partie d'un autre contrôle, tel qu'un ListBox.

Styles et ressources

Vous pouvez utiliser un style sur tout élément dérivé de FrameworkElement ou FrameworkContentElement. La méthode de déclaration d'un style la plus courante consiste à le déclarer comme une ressource dans la section Resources d'un fichier XAML, comme illustré dans les exemples précédents. Les styles étant des ressources, ils obéissent aux mêmes règles de portée qui s'appliquent à toutes les ressources ; ainsi, l'emplacement où est déclaré un style affecte l'emplacement où un style peut s'appliquer. Si, par exemple, vous déclarez le style dans l'élément racine de votre fichier de définition d'application XAML, il pourra être utilisé n'importe où dans votre application. Si vous créez une application de navigation et déclarez le style dans l'un de ses fichiers XAML, ce style ne pourra être utilisé que dans ce fichier XAML. Pour plus d'informations sur les règles de portée relatives aux ressources, consultez Vue d'ensemble des ressources.

De plus, un complément d'informations sur les styles et les ressources est disponible dans la section Ressources et thèmes partagés plus loin dans cette vue d'ensemble.

Définition de styles par programme

Pour assigner par programme un style nommé à un élément, obtenez le style de la collection de ressources et assignez-le à la propriété Style de l'élément. Notez que les éléments dans une collection de ressources sont de type Object. Vous devez donc effectuer un cast du style extrait en un Style avant de l'assigner à la propriété Style. Par exemple, pour définir le style TitleText défini sur un TextBlock nommé textblock1, procédez comme suit :

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

Notez qu'une fois qu'un style a été appliqué, il est scellé et ne peut plus être modifié. Si vous souhaitez modifier dynamiquement un style qui a déjà été appliqué, vous devez créer un style pour remplacer ce dernier. Pour plus d'informations, consultez la propriété IsSealed.

Vous pouvez créer un objet qui choisit un style à appliquer selon une logique personnalisée. Consultez l'exemple indiqué pour la classe StyleSelector.

Liaisons, ressources dynamiques et gestionnaires d'événements

Notez que vous pouvez utiliser la propriété Setter.Value pour spécifier un Binding, extension de balisage ou un Extension de balisage DynamicResource. Pour plus d'informations, consultez les exemples fournis pour la propriété Setter.Value.

Jusque-là, nous n'avons abordé que l'utilisation d'accesseurs Set pour définir la valeur de propriété. Vous pouvez également spécifier des gestionnaires d'événements dans un style. Pour plus d'informations, consultez EventSetter.

Modèles de données

Dans cet exemple d'application, un contrôle ListBox est lié à une liste de photos :

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

Ce ListBox se présente actuellement comme suit :

ListBox avant application du modèle

La plupart des contrôles ont un type de contenu quelconque, qui provient souvent des données avec lesquelles vous les liez. Dans cet exemple, les données correspondent à la liste de photos. Dans WPF, vous utilisez un DataTemplate pour définir la représentation visuelle des données. Fondamentalement, le contenu que vous placez dans un DataTemplate détermine l'apparence des données dans l'application rendue.

Dans notre exemple d'application, chaque objet Photo personnalisé a une propriété Source de chaîne de type qui spécifie le chemin d'accès du fichier de l'image. Actuellement, les objets photo apparaissent comme des chemins d'accès de fichiers.

Pour que les photos apparaissent comme des images, vous créez un DataTemplate comme une ressource :

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

Notez que la propriété DataType est très similaire à la propriété TargetType du Style. Si votre DataTemplate se trouve dans la section de ressources, lorsque vous associez la propriété DataType à un type et que vous ne lui assignez pas de x:Key, le DataTemplate est appliqué à chaque fois que ce type apparaît. Vous avez toujours la possibilité d'assigner le DataTemplate avec un x:Key, puis de le définir comme un StaticResource pour les propriétés qui prennent les types DataTemplate, comme la propriété ItemTemplate ou ContentTemplate.

Le DataTemplate indiqué dans l'exemple ci-dessus définit essentiellement que chaque fois qu'il existe un objet Photo, celui-ci doit apparaître comme un Image dans un Border. Avec ce DataTemplate, notre application se présente maintenant comme suit :

Image photo

Le modèle de création de modèles fournit d'autres fonctions. Par exemple, si vous affichez les données d'une collection contenant d'autres collections à l'aide d'un type HeaderedItemsControl tel qu'un Menu ou un TreeView, le HierarchicalDataTemplate existe. Une autre fonction de création de modèles de données est le DataTemplateSelector, qui permet de choisir le DataTemplate à utiliser selon la logique personnalisée. Pour plus d'informations, consultez Vue d'ensemble des modèles de données, qui décrit plus en détail les différentes fonctions de création de modèles de données.

Modèles de contrôle

Cette section comprend les sous-sections suivantes.

  • Sans utiliser ControlTemplate
  • Qu'est-ce qu'un ControlTemplate ?
  • Création d'un modèle de contrôle
  • Propriété IsItemsHost
  • ItemsPresenter et ContentPresenter
  • TemplateBinding

Maintenant que nos photos apparaissent comme des images, nous allons les afficher à l'horizontale et non à la verticale ; nous souhaitons rendre le ListBox horizontal.

Sans utiliser ControlTemplate

Dans un premier temps, il est important de souligner qu'il n'est pas nécessaire d'utiliser le ControlTemplate pour rendre le ListBox horizontal. Un ListBox a une propriété ItemsPanel qui permet de définir un ItemsPanelTemplate, modèle qui contrôle la disposition des éléments du ListBox. Une option consiste à créer simplement un style ListBox et à définir la propriété ItemsPanel, comme indiqué dans l'exemple suivant :

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

Cela fonctionne parfaitement et nous donne un ListBox horizontal. Cet exemple indique que, selon votre scénario, il peut y avoir des options autres que le remplacement du ControlTemplate. Pour cet exemple, si nous souhaitons un ListBox horizontal qui ait des propriétés supplémentaires, telles que des angles arrondis, nous devons alors utiliser le ControlTemplate du ListBox.

Avant de présenter un exemple illustrer la procédure à suivre, il est important d'expliquer au préalable le concept d'un ControlTemplate.

Qu'est-ce qu'un ControlTemplate ?

La plupart des contrôles ont une apparence et un comportement. Prenons, par exemple, un bouton : son apparence correspond à la zone relevée sur laquelle vous pouvez appuyer et son comportement correspond à l'événement Click déclenché en réponse à un clic.

Il peut arriver qu'un contrôle fournisse le comportement requis mais pas l'apparence dont vous avez besoin. Jusque-là, nous avons démontré que vous pouvez utiliser des accesseurs Set de style pour définir les valeurs de propriétés requises pour affecter l'apparence d'un contrôle. Toutefois, pour modifier la structure d'un contrôle ou définir des valeurs de propriétés sur les composants comprenant un contrôle, vous devez utiliser un ControlTemplate.

Dans WPF, le ControlTemplate d'un contrôle définit l'apparence de ce dernier. Vous pouvez modifier la structure et l'apparence d'un contrôle en définissant pour ce dernier un nouveau ControlTemplate. Dans de nombreux cas, cela vous donne suffisamment de souplesse pour ne pas avoir à écrire vos propres contrôles personnalisés. Si vous ne définissez pas votre propre ControlTemplate pour votre contrôle, vous obtenez le modèle par défaut correspondant au thème du système, qui est ce qui donne son apparence par défaut au contrôle Button.

Un point à ne pas oublier est qu'une fois que vous créez un ControlTemplate pour votre contrôle, vous remplacez l'intégralité du ControlTemplate. Par exemple, vous pouvez définir votre ButtonControlTemplate de la manière suivante.

Notez que l'élément ContentPresenter marque simplement l'emplacement où le Content du Button doit être placé. Nous aborderons les différents éléments plus loin.

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

Une fois ces paramètres appliqués, le Button prend la forme d'une Ellipse:

exemple de ControlTemplate de bouton

N'oubliez pas que la forme que prend le Button lorsque le focus est placé dessus ou lorsqu'il est enfoncé fait partie de l'apparence par défaut du bouton que vous remplacez. Par conséquent, selon vos besoins, vous pouvez indiquer dans votre définition la forme que doit prendre votre bouton lorsqu'il est enfoncé. Pour obtenir un exemple complet, consultez Button ControlTemplate, exemple.

Si vous créez un ControlTemplate, la meilleure méthode pour commencer consiste à utiliser le Exemples de ControlTemplate. Si vous devez vraiment observer les parties dont un contrôle est composé, vous pouvez jeter un œil au fichier des thèmes qui se trouve dans Thèmes ou vous pouvez utiliser la fonctionnalité Show Visual Tree de XAMLPad, une application installée avec le Kit de développement logiciel (SDK) Windows.

Création d'un modèle de contrôle

Nous allons poursuivre notre exemple et créer un ControlTemplate qui définit un ListBox horizontal et dont les angles sont arrondis. Pour remplacer le ControlTemplate d'un contrôle, affectez à la propriété Template la valeur du nouveau 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>

Lorsque vous définissez ainsi la propriété Template, il n'y a aucune différence par rapport à la définition d'autres propriétés de contrôle à l'aide d'un Style : vous utilisez un Style comme un outil pour vous aider à définir la propriété Template. Cela signifie qu'une autre méthode pour définir un ControlTemplate consiste à définir directement la propriété Template sur votre contrôle. Si vous procédez ainsi, vous créez alors un ControlTemplate dans la section Resources, vous lui attribuez un x:Key, puis vous l'utilisez comme une ressource statique. Pour obtenir un exemple, consultez la propriété Template.

Comme vous pouvez le voir dans l'exemple ci-dessus, la classe ControlTemplate a une propriété TargetType qui est similaire à la propriété TargetType de la classe Style. Toutefois, notez que contrairement à Style et DataTemplate, les objets ControlTemplate n'ont pas la notion d'une clé implicite. En d'autres termes, si vous avez un ControlTemplate autonome dont la propriété TargetType est associée à un type, le ControlTemplate n'est pas automatiquement appliqué à ce type. Notez également que la propriété TargetType est requise sur un modèle ControlTemplate si la définition de ce dernier contient un ContentPresenter.

Essayez de tester le ControlTemplate. Par exemple, remplacez le StackPanel par un WrapPanel, affectez à la propriété HorizontalScrollBarVisibility du ScrollViewer la valeur Disabled, puis attribuez à la largeur du ListBox la valeur 300. (Le WrapPanel place seulement des éléments sur la ligne suivante lorsqu'il n'y a plus d'espace sur la première ligne. Si vous n'affectez pas à la propriété HorizontalScrollBarVisibility du ScrollViewer la valeur Disabled, l'espace sur la première ligne suffira toujours puisque vous pourrez toujours faire défiler cette dernière jusqu'à la fin. En conséquence, le WrapPanel n'envoie pas les éléments à la ligne suivante.)

Propriété IsItemsHost

Dans cet exemple, la propriété IsItemsHost est une propriété importante qui doit exister. La propriété IsItemsHost est utilisée pour indiquer dans le modèle d'un ItemsControl (contrôles tels que ListBox qui fonctionnent avec une liste d'éléments) l'emplacement où doivent être placés les éléments générés. Affecter à la propriété la valeur true sur le StackPanel signifie que tout élément ajouté au ListBox va dans le StackPanel. Notez que cette propriété ne fonctionne que sur les types de Panel.

ItemsPresenter et ContentPresenter

Toutefois, notez que lorsque vous spécifiez un panneau dans le ControlTemplate et que vous le marquez ainsi comme IsItemsHost, le ItemsPanel ne peut pas être remplacé par l'utilisateur du contrôle sans recourir à un ControlTemplate. Par conséquent, ne procédez ainsi que si vous ne souhaitez pas que le panneau soit remplacé sans l'utilisation d'un modèle. Vous pouvez également utiliser l'élément ItemsPresenter pour marquer l'emplacement où doivent être placés les éléments, puis spécifier un ItemsPanelTemplate en définissant la propriété ItemsPanel. La page ItemsPanelTemplate contient un exemple qui vous indique comment procéder. Pour obtenir un autre exemple qui utilise le ItemsPresenter, consultez TreeView ControlTemplate, exemple.

Si vous créez un modèle pour un ContentControl tel qu'un Button, l'élément correspondant est le ContentPresenter. Similarly, you place this element in the ControlTemplate of your ContentControl type to indicate where the content should be displayed, as demonstrated in the example in the What Is a ControlTemplate? section. Pour obtenir d'autres exemples, consultez Label ControlTemplate, exemple et ListBoxItem ControlTemplate, exemple.

TemplateBinding

Un autre point important à souligner dans l'exemple précédent est la valeur Background affectée au {TemplateBinding ListBox.Background}. Cette valeur indique simplement que le Background du Border doit être synchronisé avec la valeur Background définie dans le ListBox. Un TemplateBinding est similaire à un Binding. En fait, TemplateBinding est plus efficace mais moins fonctionnel que Binding ; l'utilisation de TemplateBinding revient à utiliser Binding alors que la propriété Source a la valeur RelativeSource.TemplatedParent.

Vous utilisez TemplateBinding dans votre ControlTemplate lorsque vous souhaitez que l'utilisateur de votre contrôle puisse contrôler les valeurs de certaines propriétés. TemplateBinding est une extension de balisage représentée par la classe TemplateBindingExtension.

Vous avez probablement remarqué que le DataTemplate et le ControlTemplate sont similaires dans la mesure où leur contenu devient la visualisation d'un objet. Avec la définition ListBoxControlTemplate, notre application se présente maintenant comme suit :

Capture d'écran : exemple de styles

Déclencheurs

Style, ControlTemplate et DataTemplate ont tous une propriété Triggers qui peut contenir un jeu de déclencheurs. Un déclencheur définit des propriétés ou lance des actions telles qu'une animation lorsque la valeur d'une propriété change ou lorsqu'un événement est déclenché.

Cette section comprend les sous-sections suivantes.

  • Déclencheurs de propriété
  • EventTriggers et tables de montage séquentiel
  • MultiTriggers, DataTriggers et MultiDataTriggers

Déclencheurs de propriété

Pour démontrer comment utiliser des déclencheurs pour définir des propriétés, rendons chaque ListBoxItem partiellement transparent à moins qu'il ne soit sélectionné.

Le style suivant affecte à la propriété Opacity d'un ListBoxItem la valeur 0.5. Toutefois, lorsque la propriété IsSelected a la valeur true, Opacity a la valeur 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>

Cet exemple utilise un Trigger pour définir une valeur de propriété, mais notez que la classe Trigger a également les propriétés EnterActions et ExitActions qui permettent à un déclencheur d'exécuter des actions.

Notez que nous avons également affecté à la propriété MaxHeight du ListBoxItem la valeur 75. Dans la capture d'écran suivante, le troisième élément est l'élément sélectionné :

Vue de la liste mise en forme avec des styles

EventTriggers et tables de montage séquentiel

Nous venons de montrer qu'un Trigger définit des valeurs de propriétés ou lance des actions en fonction de la valeur d'une propriété. Un autre type de déclencheur est le EventTrigger, qui lance un jeu d'actions en fonction de l'occurrence d'un événement. Par exemple, les objets EventTrigger suivants spécifient que lorsque le pointeur de la souris entre dans le ListBoxItem, la propriété MaxHeight s'anime sur une valeur de 90 pendant une période de 0.2 seconde. Lorsque la souris s'éloigne de l'élément, la propriété retrouve sa valeur initiale sur une période de 1 seconde. Notez qu'il n'est pas nécessaire de spécifier une valeur To pour l'animation MouseLeave. Et ce car l'animation est capable d'effectuer le suivi de la valeur initiale.

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

Pour plus d'informations, consultez Vue d'ensemble des tables de montage séquentiel.

Dans la capture d'écran suivante, la souris pointe sur le troisième élément :

Capture d'écran : exemple de styles

MultiTriggers, DataTriggers et MultiDataTriggers

Outre Trigger et EventTrigger, il existe d'autres types de déclencheurs. MultiTrigger vous permet de définir des valeurs de propriétés en fonction de conditions multiples. Vous utilisez DataTrigger et MultiDataTrigger lorsque la propriété de votre condition est liée aux données.

Pour obtenir l'exemple complet présenté dans cette vue d'ensemble, consultez Introduction aux styles et aux modèles, exemple.

Ressources partagées et thèmes

Une application Windows Presentation Foundation (WPF) typique peut avoir plusieurs ressources d'interface utilisateur appliquées partout dans l'application. Collectivement, ce jeu de ressources peut être considéré comme le thème de l'application. Windows Presentation Foundation (WPF) fournit la prise en charge du conditionnement des ressources d'interface utilisateur comme un thème en utilisant un dictionnaire de ressources encapsulé comme classe ResourceDictionary.

Les thèmes Windows Presentation Foundation (WPF) sont définis à l'aide du mécanisme d'application de styles et de création de modèles que Windows Presentation Foundation (WPF) expose pour personnaliser les effets visuels de tout élément.

Les ressources du thème Windows Presentation Foundation (WPF) sont stockées dans les dictionnaires de ressources incorporés. Ces dictionnaires de ressources doivent être incorporés dans un assembly signé et ils peuvent être incorporés dans le même assembly que le code proprement dit ou dans un assembly côte à côte. Dans le cas de PresentationFramework.dll, l'assembly contenant des contrôles Windows Presentation Foundation (WPF), les ressources du thème se trouvent dans une série d'assemblys côte à côte.

Le thème devient le dernier emplacement à consulter lors de la recherche du style d'un élément. La recherche commencera généralement en remontant l'arborescence des éléments, à la recherche d'une ressource appropriée, puis en parcourant la collection des ressources de l'application et enfin en interrogeant le système. Cela permet aux auteurs de l'application de redéfinir le style de tout objet au niveau de l'arborescence ou de l'application avant d'atteindre le thème.

Vous pouvez définir des dictionnaires de ressources comme des fichiers individuels qui vous permettent de réutiliser un thème entre plusieurs applications. Vous pouvez également créer des thèmes permutables en définissant plusieurs dictionnaires de ressources qui fournissent les mêmes types de ressources mais avec des valeurs différentes. Il est recommandé de redéfinir ces styles ou d'autres ressources au niveau de l'application pour définir l'apparence d'une application.

Pour partager un jeu de ressources, y compris styles et modèles, entre les applications, vous pouvez créer un fichier XAML et définir un ResourceDictionary. Par exemple, jetez un œil à la capture d'écran suivante qui affiche une partie du Style avec ControlTemplates, exemple :

Exemples de modèle de contrôle

Si vous parcourez les fichiers XAML indiqués dans l'exemple, vous observerez que tous ont les éléments suivants :

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

C'est le partage de shared.xaml, qui définit un ResourceDictionary contenant un jeu de styles et de ressources de pinceau permettant de définir une apparence homogène des contrôles illustrés dans l'exemple.

Pour plus d'informations, consultez Dictionnaires de ressources fusionnés.

Si vous créez un thème pour votre contrôle personnalisé, jetez un œil à la section Bibliothèque de contrôles externe de la Vue d'ensemble de la création de contrôles.

Voir aussi

Tâches

Rechercher des éléments générés par ControlTemplate

Comment : rechercher des éléments générés par DataTemplate

Photo Store, démonstration

Concepts

URI à en-tête pack dans Windows Presentation Foundation

Autres ressources

Thèmes