La différence entre un bouton avec son apparence par défaut et le bouton de l'exemple précédent est que le bouton par défaut change légèrement selon son état. Par exemple, l'apparence du bouton par défaut change lorsque l'utilisateur clique dessus ou pointe sur lui. Bien que le ControlTemplate ne modifie pas la fonctionnalité d'un contrôle, il en modifie le comportement visuel. Un comportement visuel décrit l'apparence du contrôle lorsque ce dernier est dans état particulier. Pour comprendre la différence entre la fonctionnalité et le comportement visuel d'un contrôle, considérez l'exemple du bouton. La fonctionnalité du bouton consiste à déclencher l'événement Click lorsque l'utilisateur clique dessus, alors que son comportement visuel consiste à changer d'apparence lorsque l'utilisateur pointe sur lui ou clique dessus.
Vous utilisez des objets VisualState pour spécifier l'apparence d'un contrôle lorsque ce dernier est dans un état particulier. Un objet VisualState contient un Storyboard qui modifie l'apparence des éléments qui sont dans le ControlTemplate. Vous n'avez aucun code à écrire pour cela, car la logique du contrôle modifie l'état à l'aide du VisualStateManager. Lorsque le contrôle passe à l'état qui est spécifié par la propriété VisualState..::.Name, le storyboard commence. Lorsque le contrôle sort de cet état, le Storyboard cesse.
L'exemple suivant présente le VisualState qui modifie l'apparence d'un Button lorsque l'utilisateur pointe sur lui. Le Name du VisualState correspond au nom spécifié par le TemplateVisualStateAttribute dans la classe Button. Le Storyboard modifie la couleur de la bordure du bouton en modifiant la couleur du BorderBrush. Si vous vous reportez à l'exemple ControlTemplate du début de cette rubrique, vous vous souviendrez que BorderBrush est le nom du SolidColorBrush affecté au Background du Border.
<!--Change the border of the button to red when the
mouse is over the button.-->
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</vsm:VisualState>
Le contrôle est chargé de définir les états dans le cadre de son contrat de contrôle, lequel est décrit en détail dans Personnalisation des autres contrôles grâce à une bonne compréhension du contrat de contrôle, plus loin dans cette rubrique. Les états d'un contrôle sont spécifiés par le TemplateVisualStateAttribute, lequel est placé sur la définition de classe du contrôle. Un TemplateVisualStateAttribute spécifie le nom de l'état et le nom du groupe d'états auquel cet état appartient. L'exemple suivant présente les états qui sont spécifiés pour le Button.
<TemplateVisualStateAttribute(Name:="Pressed", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Focused", GroupName:="FocusStates")> _
<TemplateVisualStateAttribute(Name:="Normal", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="MouseOver", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Disabled", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Unfocused", GroupName:="FocusStates")> _
Public Class Button
Inherits ButtonBase
End Class
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
public class Button : ButtonBase
{
}
La propriété TemplateVisualStateAttribute..::.GroupName spécifie le groupe auquel appartient un état. Dans l'exemple précédent, le Button définit deux groupes d'états : le groupe CommonStates contient les états Normal, MouseOver, Pressed et Disabled Le groupe FocusStates contient les états Focused et Unfocused. Les états d'un même groupe d'état s'excluent mutuellement. Le contrôle est toujours exactement dans un état par groupe. Par exemple, un Button peut avoir le focus même lorsque le pointeur de la souris n'est pas placé dessus, de sorte qu'un Button à l'état Focused peut être à l'état MouseOver, Pressed ou Normal.
Vous ajoutez des objets VisualState à des objets VisualStateGroup. Vous ajoutez des objets VisualStateGroup à la propriété jointe VisualStateManager.VisualStateGroups, que vous définissez sur le FrameworkElement racine du ControlTemplate. L'exemple suivant définit les objets VisualState pour les états Normal, MouseOver et Pressed, lesquels figurent tous dans le groupe CommonStates. L'état Disabled et les états du groupe FocusStates sont omis pour que l'exemple reste concis, mais ils figurent dans l'exemple complet fourni dans Procédure pas à pas : personnalisation de l'apparence d'un bouton à l'aide d'un ControlTemplate.
Exécuter cet exemple
<ControlTemplate TargetType="Button"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
<Border x:Name="RootElement">
<vsm:VisualStateManager.VisualStateGroups>
<!--Define the states for the common states.
The states in the VisualStateGroup are mutually exclusive to
each other.-->
<vsm:VisualStateGroup x:Name="CommonStates">
<!--The Normal state is the state the button is in
when it is not in another state from this VisualStateGroup.-->
<vsm:VisualState x:Name="Normal" />
<!--Change the SolidColorBrush, BorderBrush, to red when the
mouse is over the button.-->
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</vsm:VisualState>
<!--Change the SolidColorBrush, BorderBrush, to Transparent when the
button is pressed.-->
<vsm:VisualState x:Name="Pressed">
<Storyboard >
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Transparent"/>
</Storyboard>
</vsm:VisualState>
<!--The Disabled state is omitted for brevity.-->
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border.Background>
<SolidColorBrush x:Name="BorderBrush" Color="Black"/>
</Border.Background>
<Grid Background="{TemplateBinding Background}" Margin="4">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="4,5,4,4" />
</Grid>
</Border>
</ControlTemplate>