Partager via


Xamarin.Forms Gestionnaire d’état visuel

Utilisez le Gestionnaire d’état visuel pour apporter des modifications aux éléments XAML en fonction des états visuels définis à partir du code.

Visual State Manager (VSM) fournit un moyen structuré d’apporter des modifications visuelles à l’interface utilisateur à partir du code. Dans la plupart des cas, l’interface utilisateur de l’application est définie en XAML, et ce code XAML inclut le balisage décrivant comment le Gestionnaire d’état visuel affecte les visuels de l’interface utilisateur.

VsM introduit le concept d’états visuels. Une Xamarin.Forms vue telle qu’une Button vue 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 Xamarin.Forms Gestionnaire d’état visuel définit un groupe d’états visuels nommé « CommonStates » avec les états visuels suivants :

  • "Normal"
  • « Désactivé »
  • « Prioritaire »
  • « Sélectionné »

Ce groupe d’états visuels est pris en charge pour toutes les classes qui dérivent VisualElementde , qui est la classe de base pour View et Page.

Vous pouvez également définir vos propres groupes d’états visuels et états visuels, comme l’illustre cet article.

Remarque

Xamarin.Forms Les développeurs familiarisés avec les déclencheurs sont conscients que 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 au déclenchement d’événements. Toutefois, l’utilisation de déclencheurs pour gérer différentes combinaisons de ces changements peut devenir assez déroutante. Historiquement, le Gestionnaire d’état visuel a été introduit dans les environnements XAML Windows pour atténuer la confusion résultant de combinaisons d’états visuels. Avec VSM, 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 courants

Le Gestionnaire d’état visuel vous permet d’inclure le balisage dans votre fichier XAML qui peut modifier l’apparence visuelle d’une vue si la vue est normale ou désactivée, ou qui a le focus d’entrée. 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.

Vous pouvez attacher le balisage VSM à une vue individuelle, ou vous pouvez le définir dans un style s’il s’applique à plusieurs vues. Les deux sections suivantes décrivent ces approches.

Balisage VSM sur une vue

Pour attacher le balisage VSM à une Entry vue, séparez d’abord les Entry balises de début et de fin :

<Entry FontSize="18">

</Entry>

Il est donné une taille de police explicite, car l’un des états utilise la FontSize propriété pour doubler la taille du texte dans le Entry.

Ensuite, insérez VisualStateManager.VisualStateGroups des balises entre ces balises :

<Entry FontSize="18">
    <VisualStateManager.VisualStateGroups>

    </VisualStateManager.VisualStateGroups>
</Entry>

VisualStateGroups est une propriété pouvant être liée attachée définie par la VisualStateManager classe. (Pour plus d’informations sur les propriétés pouvant être liées jointes, consultez l’article Propriétés jointes.) Il s’agit de la façon dont la VisualStateGroups propriété est attachée à l’objet Entry .

La propriété VisualStateGroups est de type VisualStateGroupList, qui est une collection d’objets VisualStateGroup. Dans les VisualStateManager.VisualStateGroups balises, insérez une paire de VisualStateGroup balises pour chaque groupe d’états visuels que vous souhaitez inclure :

<Entry FontSize="18">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">

        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Entry>

Notez que la VisualStateGroup balise a un x:Name attribut indiquant le nom du groupe. La VisualStateGroup classe définit une Name propriété que vous pouvez utiliser à la place :

<VisualStateGroup Name="CommonStates">

Vous pouvez utiliser l’un ou l’autre x:Name des Name deux dans le même élément.

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 VisualStateGroups sorte que vous pouvez inclure les VisualState balises directement entre les VisualStateGroup balises. (Les propriétés de contenu sont abordées dans l’article Syntaxe XAML essentielle.)

L’étape suivante consiste à inclure une paire d’étiquettes pour chaque état visuel de ce groupe. Ceux-ci peuvent également être identifiés à l’aide x:Name ou Name:

<Entry FontSize="18">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">

            </VisualState>

            <VisualState x:Name="Focused">

            </VisualState>

            <VisualState x:Name="Disabled">

            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Entry>

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 , il est donc nécessaire d’inclure VisualStatedes balises d’élément de propriété pour la Setters propriété :

<Entry FontSize="18">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">
                <VisualState.Setters>

                </VisualState.Setters>
            </VisualState>

            <VisualState x:Name="Focused">
                <VisualState.Setters>

                </VisualState.Setters>
            </VisualState>

            <VisualState x:Name="Disabled">
                <VisualState.Setters>

                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Entry>

Vous pouvez maintenant insérer un ou plusieurs Setter objets entre chaque paire d’étiquettes Setters . Voici les objets qui définissent les Setter états visuels décrits précédemment :

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

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

            <VisualState x:Name="Disabled">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="Pink" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Entry>

Chaque Setter balise indique la valeur d’une propriété particulière 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.

Le balisage similaire à celui-ci est la base de la page VSM en mode Affichage dans l’exemple de programme. La page inclut trois Entry affichages, mais seul le deuxième a le balisage VSM attaché à celui-ci :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:VsmDemos"
             x:Class="VsmDemos.MainPage"
             Title="VSM Demos">

    <StackLayout>
        <StackLayout.Resources>
            <Style TargetType="Entry">
                <Setter Property="Margin" Value="20, 0" />
                <Setter Property="FontSize" Value="18" />
            </Style>

            <Style TargetType="Label">
                <Setter Property="Margin" Value="20, 30, 20, 0" />
                <Setter Property="FontSize" Value="Large" />
            </Style>
        </StackLayout.Resources>

        <Label Text="Normal Entry:" />
        <Entry />
        <Label Text="Entry with VSM: " />
        <Entry>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="Lime" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Focused">
                        <VisualState.Setters>
                            <Setter Property="FontSize" Value="36" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Disabled">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="Pink" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Entry.Triggers>
                <DataTrigger TargetType="Entry"
                             Binding="{Binding Source={x:Reference entry3},
                                               Path=Text.Length}"
                             Value="0">
                    <Setter Property="IsEnabled" Value="False" />
                </DataTrigger>
            </Entry.Triggers>
        </Entry>
        <Label Text="Entry to enable 2nd Entry:" />
        <Entry x:Name="entry3"
               Text=""
               Placeholder="Type something to enable 2nd Entry" />
    </StackLayout>
</ContentPage>

Notez que le second Entry a également une DataTrigger partie de sa Trigger collection. Cela entraîne la Entry désactivation jusqu’à ce que quelque chose soit tapé dans le troisième Entry. Voici la page au démarrage s’exécutant sur iOS, Android et le plateforme Windows universelle (UWP) :

VSM en mode : Désactivé

L’état visuel actuel est « Désactivé » de sorte que l’arrière-plan de la seconde Entry est rose sur les écrans iOS et Android. L’implémentation UWP de Entry ne permet pas de définir la couleur d’arrière-plan lorsque la valeur Entry est désactivée.

Lorsque vous entrez du texte dans le troisième Entry, le deuxième Entry bascule dans l’état « Normal », et l’arrière-plan est désormais lime :

VSM en mode Normal

Lorsque vous touchez le deuxième Entry, il obtient le focus d’entrée. Il bascule vers l’état « Prioritaire » et s’étend à deux fois sa hauteur :

VSM en mode : Prioritaire

Notez que l’arrière-plan Entry ne conserve pas l’arrière-plan de lime lorsqu’il obtient le focus d’entrée. À 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. N’oubliez pas que les états visuels s’excluent mutuellement. L’état « Normal » ne signifie pas uniquement que l’option Entry est activée. Cela signifie que l’option Entry est activée et n’a pas de focus d’entrée.

Si vous souhaitez Entry avoir un arrière-plan lime dans l’état « Prioritaire », ajoutez-en un autre Setter à cet état visuel :

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

Pour que ces Setter objets fonctionnent correctement, un VisualStateGroup doit contenir des VisualState objets pour tous les états de ce groupe. S’il existe un état visuel qui n’a Setter pas d’objets, incluez-le quand même comme une balise vide :

<VisualState x:Name="Normal" />

Balisage Visual State Manager dans un style

Il est souvent nécessaire de partager le même balisage Visual State Manager entre deux vues ou plus. Dans ce cas, vous souhaiterez placer le balisage dans une Style définition.

Voici l’élément implicite Style existant pour les Entry éléments de la page VSM En mode Affichage :

<Style TargetType="Entry">
    <Setter Property="Margin" Value="20, 0" />
    <Setter Property="FontSize" Value="18" />
</Style>

Ajoutez des Setter balises pour la VisualStateManager.VisualStateGroups propriété pouvant être liée jointe :

<Style TargetType="Entry">
    <Setter Property="Margin" Value="20, 0" />
    <Setter Property="FontSize" Value="18" />
    <Setter Property="VisualStateManager.VisualStateGroups">

    </Setter>
</Style>

La propriété de contenu à Setter utiliser est Value, de sorte que la valeur de la Value propriété peut être spécifiée directement dans ces balises. Cette propriété est de type VisualStateGroupList:

<Style TargetType="Entry">
    <Setter Property="Margin" Value="20, 0" />
    <Setter Property="FontSize" Value="18" />
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>

        </VisualStateGroupList>
    </Setter>
</Style>

Dans ces balises, vous pouvez inclure l’un des objets suivants VisualStateGroup :

<Style TargetType="Entry">
    <Setter Property="Margin" Value="20, 0" />
    <Setter Property="FontSize" Value="18" />
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup x:Name="CommonStates">

            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

Le reste du balisage VSM est le même que précédemment.

Voici la page VSM dans style montrant le balisage VSM complet :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="VsmDemos.VsmInStylePage"
             Title="VSM in Style">
    <StackLayout>
        <StackLayout.Resources>
            <Style TargetType="Entry">
                <Setter Property="Margin" Value="20, 0" />
                <Setter Property="FontSize" Value="18" />
                <Setter Property="VisualStateManager.VisualStateGroups">
                    <VisualStateGroupList>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Lime" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Focused">
                                <VisualState.Setters>
                                    <Setter Property="FontSize" Value="36" />
                                    <Setter Property="BackgroundColor" Value="Lime" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Pink" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateGroupList>
                </Setter>
            </Style>

            <Style TargetType="Label">
                <Setter Property="Margin" Value="20, 30, 20, 0" />
                <Setter Property="FontSize" Value="Large" />
            </Style>
        </StackLayout.Resources>

        <Label Text="Normal Entry:" />
        <Entry />
        <Label Text="Entry with VSM: " />
        <Entry>
            <Entry.Triggers>
                <DataTrigger TargetType="Entry"
                             Binding="{Binding Source={x:Reference entry3},
                                               Path=Text.Length}"
                             Value="0">
                    <Setter Property="IsEnabled" Value="False" />
                </DataTrigger>
            </Entry.Triggers>
        </Entry>
        <Label Text="Entry to enable 2nd Entry:" />
        <Entry x:Name="entry3"
               Text=""
               Placeholder="Type something to enable 2nd Entry" />
    </StackLayout>
</ContentPage>

À présent, toutes les Entry vues de cette page répondent de la même façon à leurs états visuels. Notez également que l’état « Prioritaire » inclut désormais une seconde Setter qui donne à chaque Entry arrière-plan de lime également lorsqu’il a le focus d’entrée :

VSM dans le style

États visuels dans Xamarin.Forms

Le tableau suivant répertorie les états visuels définis dans Xamarin.Forms:

Classe États Informations supplémentaires
Button Pressed États visuels de Button
CheckBox IsChecked États visuels de CheckBox
CarouselView DefaultItem, , CurrentItemPreviousItem, ,NextItem États visuels de CarouselView
ImageButton Pressed États visuels d’ImageButton
RadioButton Checked, Unchecked États visuels de RadioButton
Switch On, Off États visuels de Switch
VisualElement Normal, , DisabledFocused, ,Selected États courants

Chacun de ces états est accessible via le groupe d’états visuels nommé CommonStates.

En outre, l’état CollectionView est implémenté Selected . Pour plus d’informations, consultez Modifier la couleur d’élément sélectionnée.

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 Setter type a une TargetName propriété, de type string, qui représente l’élément cible que le Setter pour un état visuel manipulera. Lorsque la TargetName propriété est définie, la Setter propriété définit l’élément Property défini dans TargetName :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.

La page VSM avec Setter TargetName dans l’exemple montre comment définir l’état sur plusieurs éléments, à partir d’un seul groupe d’états visuels. Le fichier XAML se compose d’un StackLayout élément, d’un Label Entryélément et d’un Button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="VsmDemos.VsmSetterTargetNamePage"
             Title="VSM with Setter TargetName">
    <StackLayout Margin="10">
        <Label Text="What is the capital of France?" />
        <Entry x:Name="entry"
               Placeholder="Enter answer" />
        <Button Text="Reveal answer">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x: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>
</ContentPage>

Le balisage VSM est attaché au StackLayout. Il existe deux états mutuellement exclusifs, nommés « Normal » et « Pressed », avec chaque état contenant des VisualState balises.

L’état « Normal » est actif lorsque l’état Button n’est pas appuyé et qu’une réponse à la question peut être entrée :

VSM Setter TargetName : État normal

L’état « Appuyé » devient actif lorsque l’état Button est appuyé :

VSM Setter TargetName : État appuyé

L’argument « Pressed » VisualState spécifie que lorsque la Button propriété est enfoncée, sa Scale propriété est remplacée par la valeur par défaut de 1 à 0,8. En outre, l’Entry nommée entry aura sa propriété Text définie sur Paris. Par conséquent, le résultat est que lorsque la Button pression est enfoncée, elle est rescaled pour être légèrement plus petite, et les Entry affiches Paris. 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 actuellement pas pris en charge dans Setter les éléments qui spécifient la TargetName propriété.

Définir vos propres états visuels

Chaque classe dérivée de VisualElement la prise en charge des états communs « Normal », « Prioritaire » et « Désactivé ». En outre, la CollectionView classe prend en charge l’état « Sélectionné ». En interne, la VisualElement classe détecte quand elle est activée ou désactivée, ou centrée ou non centrée, et appelle la méthode statique VisualStateManager.GoToState :

VisualStateManager.GoToState(this, "Focused");

Il s’agit du seul code Visual State Manager que vous trouverez dans la VisualElement classe. Étant donné qu’il GoToState est appelé pour chaque objet basé sur chaque classe qui dérive de VisualElement, vous pouvez utiliser le Gestionnaire d’état visuel avec n’importe quel VisualElement objet pour répondre à ces modifications.

Il est intéressant de noter que le nom du groupe d’états visuels « CommonStates » n’est pas explicitement référencé dans VisualElement. Le nom du groupe ne fait pas partie de l’API du Gestionnaire d’état visuel. Dans l’un des deux exemples de programme affichés jusqu’à présent, vous pouvez remplacer le nom du groupe par « CommonStates » par tout autre élément, et le programme fonctionnera toujours. Le nom du groupe est simplement une description générale des états de ce groupe. Il est implicitement compris que les états visuels d’un groupe sont mutuellement exclusifs : un état et un seul état est actif à tout moment.

Si vous souhaitez implémenter vos propres états visuels, vous devez appeler VisualStateManager.GoToState à partir du code. Le plus souvent, vous effectuerez cet appel à partir du fichier code-behind de votre classe de page.

La page Validation VSM de l’exemple montre comment utiliser visual State Manager en connexion avec la validation d’entrée. Le fichier XAML se compose d’un StackLayout contenant deux Label éléments, un Entryet un Button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             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="Large" />
        <Entry x:Name="entry"
               Placeholder="555-555-5555"
               FontSize="Large"
               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="Large"
                Margin="0, 20"
                VerticalOptions="Center"
                HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

Le balisage VSM est attaché au StackLayout (nommé stackLayout). Il existe deux états mutuellement exclusifs, nommés « Valide » et « Non valides », avec chaque état contenant des VisualState balises.

Si le Entry numéro de téléphone n’est pas valide, l’état actuel est « Non valide », et le Entry second est donc visible, le second Label est visible et l’état Button actuel est désactivé :

Validation VSM : État non valide

Lorsqu’un numéro de téléphone valide est entré, l’état actuel devient « Valide ». L’Entry reçoit un arrière-plan vert-citron, la seconde Label disparaît, et le Button est désormais activé :

Validation VSM : État valide

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 du fichier code-behind nommé GoToState appelle la méthode statique VisualStateManager.GoToState pour 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);
    }
}

Notez également que la GoToState méthode est appelée à partir du constructeur pour initialiser l’état. Il doit toujours y avoir un état actuel. Mais nulle part dans le code n’existe aucune référence au nom du groupe d’états visuels, bien qu’elle soit référencée dans le code XAML comme « ValidationStates » à des fins de clarté.

Notez que le fichier code-behind doit uniquement tenir compte de l’objet sur la page qui définit les états visuels et d’appeler VisualStateManager.GoToState cet objet. Cela est dû au fait que les deux états visuels ciblent plusieurs objets sur la page.

Vous pouvez vous demander : si le fichier code-behind doit référencer l’objet sur la page qui définit les états visuels, pourquoi le fichier code-behind ne peut-il pas simplement accéder directement à ce fichier et à d’autres objets ? C’est sûr. Toutefois, l’avantage de l’utilisation de VSM est que vous pouvez contrôler la façon dont les éléments visuels réagissent à un état différent entièrement en XAML, ce qui conserve toute la conception de l’interface utilisateur dans un seul emplacement. Cela évite de définir l’apparence visuelle en accédant directement aux éléments visuels à partir du code-behind.

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, Xamarin.Forms utilise les règles de précédence suivantes pour déterminer quel déclencheur (et correspondant VisualState) 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.

Utiliser le Gestionnaire d’état visuel pour la disposition adaptative

Une Xamarin.Forms application s’exécutant sur un téléphone peut généralement être vue dans un rapport d’aspect portrait ou paysage, et un Xamarin.Forms programme s’exécutant sur le bureau peut être redimensionné pour supposer de nombreuses tailles et proportions différentes. Une application bien conçue peut afficher son contenu différemment pour ces différents facteurs de forme de page ou de fenêtre.

Cette technique est parfois appelée disposition adaptative. Étant donné que la disposition adaptative implique uniquement les visuels d’un programme, il s’agit d’une application idéale du Gestionnaire d’état visuel.

Un exemple simple est une application qui affiche une petite collection de boutons qui affectent le contenu de l’application. En mode Portrait, ces boutons peuvent être affichés dans une ligne horizontale en haut de la page :

Disposition adaptative VSM : Portrait

En mode paysage, le tableau de boutons peut être déplacé d’un côté et affiché dans une colonne :

Disposition adaptative VSM : Paysage

De haut en bas, le programme s’exécute sur les plateforme Windows universelle, Android et iOS.

La page Mise en page adaptative VSM de l’exemple définit un groupe nommé « OrientationStates » avec deux états visuels nommés « Portrait » et « Paysage ». (Une approche plus complexe peut être basée sur plusieurs largeurs de page ou de fenêtre différentes.)

Le balisage VSM se produit à quatre emplacements dans le fichier XAML. Le StackLayout nom mainStack contient à la fois le menu et le contenu, qui est un Image élément. Cela StackLayout doit avoir une orientation verticale en mode portrait et une orientation horizontale en mode paysage :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="VsmDemos.VsmAdaptiveLayoutPage"
             Title="VSM Adaptive Layout">

    <StackLayout x:Name="mainStack">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="OrientationStates">
                <VisualState Name="Portrait">
                    <VisualState.Setters>
                        <Setter Property="Orientation" Value="Vertical" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState Name="Landscape">
                    <VisualState.Setters>
                        <Setter Property="Orientation" Value="Horizontal" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <ScrollView x:Name="menuScroll">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="OrientationStates">
                    <VisualState Name="Portrait">
                        <VisualState.Setters>
                            <Setter Property="Orientation" Value="Horizontal" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState Name="Landscape">
                        <VisualState.Setters>
                            <Setter Property="Orientation" Value="Vertical" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <StackLayout x:Name="menuStack">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup Name="OrientationStates">
                        <VisualState Name="Portrait">
                            <VisualState.Setters>
                                <Setter Property="Orientation" Value="Horizontal" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState Name="Landscape">
                            <VisualState.Setters>
                                <Setter Property="Orientation" Value="Vertical" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>

                <StackLayout.Resources>
                    <Style TargetType="Button">
                        <Setter Property="VisualStateManager.VisualStateGroups">
                            <VisualStateGroupList>
                                <VisualStateGroup Name="OrientationStates">
                                    <VisualState Name="Portrait">
                                        <VisualState.Setters>
                                            <Setter Property="HorizontalOptions" Value="CenterAndExpand" />
                                            <Setter Property="Margin" Value="10, 5" />
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState Name="Landscape">
                                        <VisualState.Setters>
                                            <Setter Property="VerticalOptions" Value="CenterAndExpand" />
                                            <Setter Property="HorizontalOptions" Value="Center" />
                                            <Setter Property="Margin" Value="10" />
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateGroupList>
                        </Setter>
                    </Style>
                </StackLayout.Resources>

                <Button Text="Banana"
                        Command="{Binding SelectedCommand}"
                        CommandParameter="Banana.jpg" />
                <Button Text="Face Palm"
                        Command="{Binding SelectedCommand}"
                        CommandParameter="FacePalm.jpg" />
                <Button Text="Monkey"
                        Command="{Binding SelectedCommand}"
                        CommandParameter="monkey.png" />
                <Button Text="Seated Monkey"
                        Command="{Binding SelectedCommand}"
                        CommandParameter="SeatedMonkey.jpg" />
            </StackLayout>
        </ScrollView>

        <Image x:Name="image"
               VerticalOptions="FillAndExpand"
               HorizontalOptions="FillAndExpand" />
    </StackLayout>
</ContentPage>

Le nom menuScroll interne ScrollView et le StackLayout nom menuStack implémentent le menu des boutons. L’orientation de ces dispositions est opposée à mainStack. Le menu doit être horizontal en mode portrait et vertical en mode paysage.

La quatrième section du balisage VSM est dans un style implicite pour les boutons eux-mêmes. Ce balisage définit VerticalOptions, HorizontalOptionset Margin les propriétés spécifiques aux orientations portrait et paysage.

Le fichier code-behind définit la BindingContext propriété de l’implémentation Button de menuStack commandes et attache également un gestionnaire à l’événement SizeChanged de la page :

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

        SizeChanged += (sender, args) =>
        {
            string visualState = Width > Height ? "Landscape" : "Portrait";
            VisualStateManager.GoToState(mainStack, visualState);
            VisualStateManager.GoToState(menuScroll, visualState);
            VisualStateManager.GoToState(menuStack, visualState);

            foreach (View child in menuStack.Children)
            {
                VisualStateManager.GoToState(child, visualState);
            }
        };

        SelectedCommand = new Command<string>((filename) =>
        {
            image.Source = ImageSource.FromResource("VsmDemos.Images." + filename);
        });

        menuStack.BindingContext = this;
    }

    public ICommand SelectedCommand { private set; get; }
}

Le SizeChanged gestionnaire appelle VisualStateManager.GoToState les deux StackLayout et ScrollView les éléments, puis effectue une boucle dans les enfants de menuStack l’appel VisualStateManager.GoToState des Button éléments.

Il peut sembler que si le fichier code-behind peut gérer les modifications d’orientation plus directement en définissant des propriétés d’éléments dans le fichier XAML, mais visual State Manager est certainement une approche plus structurée. Tous les visuels sont conservés dans le fichier XAML, où ils deviennent plus faciles à examiner, gérer et modifier.

Visual State Manager avec Xamarin.University

Xamarin.Forms Vidéo du Gestionnaire d’état visuel 3.0