Partager via


États visuels

Le Gestionnaire d’état visuel .NET Multi-platform App UI (.NET MAUI) offre un moyen structuré d’apporter des modifications visuelles à l’interface utilisateur à partir du code. Dans la plupart des cas, l’interface utilisateur d’une application est définie en XAML, et ce XAML peut inclure du balisage décrivant comment le Gestionnaire d’état visuel affecte les visuels de l’interface utilisateur.

Le Gestionnaire d’état visuel introduit le concept d’états visuels. Une vue .NET MAUI telle qu’un Button peut avoir plusieurs apparences visuelles différentes en fonction de son état sous-jacent, qu’elle soit désactivée ou enfoncée, ou qu’elle ait le focus d’entrée. Il s’agit des états du bouton. Les états visuels sont collectés dans des groupes d’états visuels. Tous les états visuels d’un groupe d’états visuels s’excluent mutuellement. Les états visuels et les groupes d’états visuels sont identifiés par des chaînes de texte simples.

Le Gestionnaire d’état visuel .NET MAUI définit un groupe d’états visuels nommé CommonStates avec les états visuels suivants :

  • Normal
  • Désactivé
  • Prioritaire
  • Volumes sélectionnés
  • PointerOver

Les états visuels Normal, Disabled, Focused et PointerOver sont pris en charge sur toutes les classes qui dérivent de VisualElement, qui est la classe de base pour View et Page. En outre, vous pouvez également définir vos propres groupes d’états visuels et états visuels.

L’avantage de l’utilisation du Gestionnaire d’état visuel pour définir l’apparence, plutôt que d’accéder directement aux éléments visuels à partir de code-behind, est que vous pouvez contrôler la façon dont les éléments visuels réagissent à différents états entièrement en XAML, ce qui conserve toute la conception de l’interface utilisateur dans un emplacement unique.

Remarque

Les déclencheurs peuvent également apporter des modifications aux visuels dans l’interface utilisateur en fonction des modifications apportées aux propriétés d’une vue ou du déclenchement d’événements. Toutefois, l’utilisation de déclencheurs pour gérer différentes combinaisons de ces modifications peut devenir déroutante. Avec le Gestionnaire d’état visuel, les états visuels au sein d’un groupe d’états visuels sont toujours mutuellement exclusifs. À tout moment, un seul état dans chaque groupe est l’état actuel.

États visuels courants

Le Gestionnaire d’état visuel vous permet d’inclure du balisage dans votre fichier XAML qui peut changer l’apparence visuelle d’une vue si celle-ci est normale, désactivée, a le focus d’entrée, est sélectionnée, ou si le curseur de la souris pointe dessus sans qu’il y ait enfoncement du bouton. Il s’agit des états courants.

Par exemple, supposez que vous disposez d’une vue Entry sur votre page, et que vous souhaitez que l’apparence visuelle d’Entry change des manières suivantes :

  • L’Entry doit avoir un arrière-plan rose lorsque l’Entry est désactivée.
  • L’Entry doit normalement avoir un arrière-plan vert-citron.
  • L’Entry doit être étendue à deux fois sa hauteur normale lorsqu’elle a le focus d’entrée.
  • L’Entry doit avoir un arrière-plan bleu clair lorsque le curseur de la souris pointe dessus sans qu’il y ait enfoncement du bouton.

Vous pouvez attacher le balisage de Gestionnaire d’état visuel à une vue spécifique, ou vous pouvez le définir dans un style s’il s’applique à plusieurs vues.

Définir des états visuels sur une vue

La classe VisualStateManager définit une propriété jointe VisualStateGroups, utilisée pour attacher des états visuels à une vue. La propriété VisualStateGroups est de type VisualStateGroupList, qui est une collection d’objets VisualStateGroup. Par conséquent, l’enfant de la propriété jointe VisualStateManager.VisualStateGroups est un objet VisualStateGroup. Cet objet définit un attribut x:Name qui indique le nom du groupe. La classe VisualStateGroup définit également une propriété Name que vous pouvez utiliser à la place. Pour plus d’informations sur les propriétés jointes, consultez Propriétés jointes.

La classe VisualStateGroup définit une propriété nommée States, qui est une collection d’objets VisualState. States est la propriété de contenu de la classe VisualStateGroups ; vous pouvez donc inclure les objets VisualState en tant qu’enfants du VisualStateGroup. Chaque objet VisualState doit être identifié à l’aide de x:Name ou Name.

La classe VisualState définit une propriété nommée Setters, qui est une collection d’objets Setter. Il s’agit des mêmes objets Setter que ceux que vous utilisez dans un objet Style. Setters n’est pas la propriété de contenu de VisualState ; il est donc nécessaire d’inclure des balises d’élément de propriété pour la propriété Setters. Les objets Setter doivent être insérés en tant qu’enfants de Setters. Chaque objet Setter indique la valeur d’une propriété lorsque cet état est actif. Toute propriété référencée par un objet Setter doit être secondée par une propriété pouvant être liée.

Important

Pour que les objets Setter d’état visuel fonctionnent correctement, un VisualStateGroup doit contenir un objet VisualState pour l’état Normal. Si cet état visuel n’a aucun objet Setter, il doit être inclus en tant qu’état visuel vide (<VisualState Name="Normal" />).

L’exemple suivant montre des états visuels définis sur une Entry :

<Entry FontSize="18">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroupList>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="Lime" />
                    </VisualState.Setters>
                </VisualState>

                <VisualState Name="Focused">
                    <VisualState.Setters>
                        <Setter Property="FontSize" Value="36" />
                    </VisualState.Setters>
                </VisualState>

                <VisualState Name="Disabled">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="Pink" />
                    </VisualState.Setters>
                </VisualState>

                <VisualState Name="PointerOver">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="LightBlue" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </VisualStateManager.VisualStateGroups>
</Entry>

La capture d’écran suivante montre l’Entry dans ses quatre états visuels définis :

Capture d’écran des trois états visuels définis sur l’Entry.

Lorsque l’Entry est à l’état Normal, son arrière-plan est vert-citron. Lorsque l’Entry reçoit le focus d’entrée, sa taille de police double. Lorsque l’Entry devient désactivée, son arrière-plan devient rose. L’Entry ne conserve pas son arrière-plan vert-citron lorsqu’elle reçoit le focus d’entrée. Lorsque le pointeur de la souris est sur l’Entry, mais que le bouton n’est pas enfoncé, l’arrière-plan de l’Entry devient bleu clair. À mesure que le Gestionnaire d’état visuel bascule entre les états visuels, les propriétés définies par l’état précédent sont annulées. Par conséquent, les états visuels s’excluent mutuellement.

Si vous souhaitez que l’Entry ait un arrière-plan vert-citron à l’état Focused, ajoutez un autre Setter à cet état visuel :

<VisualState Name="Focused">
    <VisualState.Setters>
        <Setter Property="FontSize" Value="36" />
        <Setter Property="BackgroundColor" Value="Lime" />
    </VisualState.Setters>
</VisualState>

Définir des états visuels dans un style

Il est souvent nécessaire de partager les mêmes états visuels dans plusieurs vues. Dans ce scénario, les états visuels peuvent être définis dans un Style. Vous pouvez pour cela ajouter un objet Setter pour la propriété VisualStateManager.VisualStateGroups. La propriété de contenu de l’objet Setter est sa propriété Value, qui peut donc être spécifiée en tant qu’enfant de l’objet Setter. La propriété VisualStateGroups est de type VisualStateGroupList ; l’enfant de l’objet Setter est donc un VisualStateGroupList auquel un VisualStateGroup qui contient des objets VisualState peut être ajouté.

L’exemple suivant montre un style implicite pour une Entry qui définit les états visuels courants :

<Style TargetType="Entry">
    <Setter Property="FontSize" Value="18" />
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="Lime" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState Name="Focused">
                    <VisualState.Setters>
                        <Setter Property="FontSize" Value="36" />
                        <Setter Property="BackgroundColor" Value="Lime" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState Name="Disabled">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="Pink" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState Name="PointerOver">
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor" Value="LightBlue" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

Lorsque ce style est inclus dans un dictionnaire de ressources au niveau de la page, l’objet Style est appliqué à tous les objets Entry de la page. Par conséquent, tous les objets Entry de la page répondent de la même façon à leurs états visuels.

États visuels dans .NET MAUI

Le tableau suivant répertorie les états visuels définis dans .NET MAUI :

Classe États Informations supplémentaires
Button Pressed États visuels de Button
CarouselView DefaultItem, CurrentItem, PreviousItem, NextItem États visuels de CarouselView
CheckBox IsChecked États visuels de CheckBox
CollectionView Selected États visuels de CollectionView
ImageButton Pressed États visuels d’ImageButton
RadioButton Checked, Unchecked États visuels de RadioButton
Switch On, Off États visuels de Switch
VisualElement Normal, Disabled, Focused, PointerOver États courants

Définir l’état sur plusieurs éléments

Dans les exemples précédents, les états visuels étaient attachés à, et opéraient sur, des éléments uniques. Toutefois, il est également possible de créer des états visuels attachés à un élément unique, mais qui définissent des propriétés sur d’autres éléments dans la même étendue. Cela évite de devoir répéter les états visuels sur chaque élément sur lequel les états opèrent.

Le type Setter a une propriété TargetName, de type string, qui représente l’objet cible que le Setter pour un état visuel manipulera. Lorsque la propriété TargetName est définie, le Setter définit le Property de l’objet défini dans TargetName sur Value :

<Setter TargetName="label"
        Property="Label.TextColor"
        Value="Red" />

Dans cet exemple, une Label nommée label aura sa propriété TextColor définie sur Red. Lorsque vous définissez la propriété TargetName, vous devez spécifier le chemin d’accès complet à la propriété dans Property. Par conséquent, pour définir la propriété TextColor sur une Label, Property est spécifié comme Label.TextColor.

Remarque

Toute propriété référencée par un objet Setter doit être secondée par une propriété pouvant être liée.

L’exemple suivant montre comment définir l’état sur plusieurs objets, à partir d’un groupe d’états visuels unique :

<StackLayout>
    <Label Text="What is the capital of France?" />
    <Entry x:Name="entry"
           Placeholder="Enter answer" />
    <Button Text="Reveal answer">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal" />
                <VisualState Name="Pressed">
                    <VisualState.Setters>
                        <Setter Property="Scale"
                                Value="0.8" />
                        <Setter TargetName="entry"
                                Property="Entry.Text"
                                Value="Paris" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Button>
</StackLayout>

Dans cet exemple, l’état Normal est actif lorsque le Button n’est pas enfoncé, et une réponse peut être tapée dans l’Entry. L’état Pressed devient actif lorsque le Button est enfoncé, et spécifie que sa propriété Scale sera modifiée en remplaçant la valeur par défaut (1) par 0,8. En outre, l’Entry nommée entry aura sa propriété Text définie sur Paris. Le résultat est que lorsque le Button est enfoncé, il est remis à l’échelle afin d’être légèrement plus petit, et l’Entry affiche Paris :

Capture d’écran de l’état Enfoncé pour un Button.

Ensuite, lorsque le Button est relâché, il est remis à l’échelle à sa valeur par défaut de 1, et l’Entry affiche tout texte précédemment entré.

Important

Les chemins de propriété ne sont pas pris en charge dans les éléments Setter qui spécifient la propriété TargetName.

Définir des états visuels personnalisés

Les états visuels personnalisés peuvent être implémentés en les définissant comme vous le feriez pour les états courants, mais avec les noms de votre choix, puis en appelant la méthode VisualStateManager.GoToState pour activer un état.

L’exemple suivant montre comment utiliser le Gestionnaire d’état visuel pour la validation d’entrée :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="VsmDemos.VsmValidationPage"
             Title="VSM Validation">
    <StackLayout x:Name="stackLayout"
                 Padding="10, 10">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="ValidityStates">
                    <VisualState Name="Valid">
                        <VisualState.Setters>
                            <Setter TargetName="helpLabel"
                                    Property="Label.TextColor"
                                    Value="Transparent" />
                            <Setter TargetName="entry"
                                    Property="Entry.BackgroundColor"
                                    Value="Lime" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState Name="Invalid">
                        <VisualState.Setters>
                            <Setter TargetName="entry"
                                    Property="Entry.BackgroundColor"
                                    Value="Pink" />
                            <Setter TargetName="submitButton"
                                    Property="Button.IsEnabled"
                                    Value="False" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        <Label Text="Enter a U.S. phone number:"
               FontSize="18" />
        <Entry x:Name="entry"
               Placeholder="555-555-5555"
               FontSize="18"
               Margin="30, 0, 0, 0"
               TextChanged="OnTextChanged" />
        <Label x:Name="helpLabel"
               Text="Phone number must be of the form 555-555-5555, and not begin with a 0 or 1" />
        <Button x:Name="submitButton"
                Text="Submit"
                FontSize="18"
                Margin="0, 20"
                VerticalOptions="Center"
                HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

Dans cet exemple, des états visuels sont attachés au StackLayout, et il existe deux états mutuellement exclusifs nommés Valid et Invalid. Si l’Entry ne contient pas de numéro de téléphone valide, l’état actuel est Invalid, et l’Entry a donc un fond rose, la secondeLabel est visible, et le Button est désactivé. Lorsqu’un numéro de téléphone valide est entré, l’état actuel devient Valid. L’Entry reçoit un arrière-plan vert-citron, la seconde Label disparaît, et le Button est désormais activé :

Capture d’écran de l’exemple de validation de l’état visuel.

Le fichier code-behind est chargé de gérer l’événement TextChanged à partir de l’Entry. Le gestionnaire utilise une expression régulière pour déterminer si la chaîne d’entrée est valide ou non. La méthode GoToState dans le fichier code-behind appelle la méthode statique VisualStateManager.GoToState sur l’objet StackLayout :

public partial class VsmValidationPage : ContentPage
{
    public VsmValidationPage()
    {
        InitializeComponent();

        GoToState(false);
    }

    void OnTextChanged(object sender, TextChangedEventArgs args)
    {
        bool isValid = Regex.IsMatch(args.NewTextValue, @"^[2-9]\d{2}-\d{3}-\d{4}$");
        GoToState(isValid);
    }

    void GoToState(bool isValid)
    {
        string visualState = isValid ? "Valid" : "Invalid";
        VisualStateManager.GoToState(stackLayout, visualState);
    }
}

Dans cet exemple, la méthode GoToState est appelée à partir du constructeur pour initialiser l’état. Il doit toujours y avoir un état actuel. Le fichier code-behind appelle ensuite VisualStateManager.GoToState, avec un nom d’état, sur l’objet qui définit les états visuels.

Déclencheurs d’état visuel

Les états visuels prennent en charge les déclencheurs d’état, qui sont un groupe spécialisé de déclencheurs qui définissent les conditions dans lesquelles un VisualState doit être appliqué.

Les déclencheurs d’état sont ajoutés à la collection StateTriggers d’un VisualState. Cette collection peut contenir un seul ou plusieurs déclencheurs d’état. Un VisualState est appliqué lorsqu’un déclencheur d’état de la collection est actif.

Lorsque vous utilisez des déclencheurs d’état pour contrôler les états visuels, .NET MAUI utilise les règles de précédence suivantes pour déterminer quel déclencheur (et VisualState correspondant) sera actif :

  1. Tout déclencheur dérivé de StateTriggerBase.
  2. Un AdaptiveTrigger activé en raison de la satisfaction de la condition MinWindowWidth.
  3. Un AdaptiveTrigger activé en raison de la satisfaction de la condition MinWindowHeight.

Si plusieurs déclencheurs sont actifs simultanément (par exemple, deux déclencheurs personnalisés), le premier déclencheur déclaré dans le balisage est prioritaire.

Pour plus d’informations sur les déclencheurs d’état, consultez Déclencheurs d’état.