Xamarin.Forms Gestionnaire d’état visuel

Télécharger l’exemple Télécharger l’exemple

Utilisez visual State Manager 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 visual State Manager affecte les visuels de l’interface utilisateur.

Le VSM introduit le concept d’états visuels. Une Xamarin.Forms vue 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.

Visual Xamarin.Forms State Manager définit un groupe d’états visuels nommé « CommonStates » avec les états visuels suivants :

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

Ce groupe d’états visuels est pris en charge pour toutes les classes qui dérivent de VisualElement, 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 le montre cet article.

Notes

Xamarin.Forms les développeurs familiarisés avec les déclencheurs savent 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 du déclenchement d’événements. Toutefois, l’utilisation de déclencheurs pour traiter diverses combinaisons de ces modifications peut devenir assez déroutante. Historiquement, visual State Manager a été introduit dans les environnements XAML Windows pour atténuer la confusion résultant des combinaisons d’états visuels. Avec le 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 communs

Visual State Manager vous permet d’inclure un balisage dans votre fichier XAML qui peut modifier l’apparence visuelle d’une vue si la vue est normale ou désactivée, ou si le focus d’entrée est activé. Ces états sont appelés états communs.

Par exemple, supposons que vous ayez une Entry vue sur votre page et que vous souhaitiez que l’apparence visuelle du Entry change de la manière suivante :

  • doit Entry avoir un arrière-plan rose lorsque le Entry est désactivé.
  • Le Entry doit avoir un fond de chaux normalement.
  • Le Entry doit atteindre deux fois sa hauteur normale lorsqu’il 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, commencez par séparer le Entry en balises de début et de fin :

<Entry FontSize="18">

</Entry>

Il reçoit une taille de police explicite, car l’un des états utilise la FontSize propriété pour doubler la taille du texte dans .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 définie par la VisualStateManager classe . (Pour plus d’informations sur les propriétés liées attachées, consultez l’article Propriétés jointes.) C’est ainsi que la VisualStateGroups propriété est attachée à l’objet Entry .

La VisualStateGroups propriété 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 x:Name ou mais Name pas les deux dans le même élément.

La VisualStateGroup classe définit une propriété nommée States, qui est une collection d’objets VisualState . States est la propriété content de VisualStateGroups afin que vous puissiez 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. Vous pouvez également les identifier à l’aide de 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 Setter objets que ceux que vous utilisez dans un Style objet.

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 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 de Setters balises. Voici les Setter objets qui définissent les é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 actuel. Toute propriété référencée par un Setter objet doit être soutenue par une propriété pouvant être liée.

Le balisage similaire à celui-ci est la base de la page VSM on View dans l’exemple de programme VsmDemos . La page comprend trois Entry affichages, mais seule la deuxième est associée au balisage VSM :

<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 un DataTrigger dans sa Trigger collection. Cela entraîne la désactivation de jusqu’à Entry 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 à l’affichage : vsm désactivé

L’état visuel actuel étant « Désactivé », l’arrière-plan du second Entry est rose sur les écrans iOS et Android. L’implémentation UWP de ne permet pas de Entry définir la couleur d’arrière-plan lorsque le Entry est désactivé.

Lorsque vous entrez du texte dans le troisième Entry, le second Entry passe à l’état « Normal » et l’arrière-plan est maintenant lime :

VSM à l’affichage : VSM normal

Lorsque vous appuyez sur le deuxième Entry, il obtient le focus d’entrée. Il passe à l’état « Focus » et s’étend à deux fois sa hauteur :

VSM à l’affichage : VSM concentré

Notez que le Entry ne conserve pas l’arrière-plan lime lorsqu’il obtient le focus d’entrée. Lorsque le Gestionnaire d’état visuel bascule entre les états visuels, les propriétés définies par l’état précédent ne sont pas définies. N’oubliez pas que les états visuels s’excluent mutuellement. L’état « Normal » ne signifie pas uniquement que le Entry est activé. Cela signifie que le est activé et n’a pas de Entry focus d’entrée.

Si vous souhaitez que le Entry ait un arrière-plan lime à l’état « Focus », 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 doit contenir des VisualStateGroupVisualState objets pour tous les états de ce groupe. S’il existe un état visuel qui n’a aucun Setter objet, 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 devez placer le balisage dans une Style définition.

Voici l’implicite Style existant pour les éléments de la Entry page VSM à l’affichage :

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

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

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

    </Setter>
</Style>

La propriété content pour Setter 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 autres VisualStateGroup objets :

<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 qu’auparavant.

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>

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

VSM dans Style

États visuels dans Xamarin.Forms

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

Classe États Informations complémentaires
Button Pressed États visuels du bouton
CheckBox IsChecked États visuels CheckBox
CarouselView DefaultItem, CurrentItem, PreviousItem, NextItem États visuels CarouselView
ImageButton Pressed États visuels ImageButton
RadioButton Checked, Unchecked États visuels RadioButton
Switch On, Off Changer d’état visuel
VisualElement Normal, Disabled, Focused, Selected États communs

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

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

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

Dans les exemples précédents, les états visuels ont été attachés à des éléments uniques et ont été utilisés sur eux. Toutefois, il est également possible de créer des états visuels qui sont attachés à un seul élément, mais qui définissent des propriétés sur d’autres éléments dans la même étendue. Cela évite d’avoir à répéter des é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 va manipuler. Lorsque la TargetName propriété est définie, le Setter définit de l’élément Property défini dans sur ValueTargetName :

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

Dans cet exemple, une Label propriété nommée label a TextColor la Redvaleur . Lorsque vous définissez la TargetName propriété, vous devez spécifier le chemin d’accès complet à la propriété dans Property. Par conséquent, pour définir la TextColor propriété sur un Label, Property est spécifié en tant que Label.TextColor.

Notes

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

La page VSM avec Setter TargetName dans l’exemple VsmDemos 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 contenant un Label élément, un Entryet 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é à .StackLayout Il existe deux états mutuellement exclusifs, nommés « Normal » et « Pressed », chaque état contenant des VisualState balises.

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

VSM Setter TargetName : état normal

L’état « Pressed » devient actif lorsque le Button est enfoncé :

VSM Setter TargetName : État pressed

L’option « Pressed » VisualState spécifie que lorsque la Button est enfoncée, sa Scale propriété passe de la valeur par défaut de 1 à 0,8. En outre, le Entry nommé entry aura sa Text propriété définie sur Paris. Par conséquent, le résultat est que lorsque le Button est enfoncé, il est redimensionné pour être légèrement plus petit, et les Entry affiches Paris. Ensuite, lorsque le Button est libéré, il est redimensionné à sa valeur par défaut de 1, et le 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 prend en charge les états communs « Normal », « Focus » et « Disabled ». En outre, la CollectionView classe prend en charge l’état « Sélectionné ». En interne, la VisualElement classe détecte quand elle devient activée ou désactivée, ou concentrée ou non ciblé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é que GoToState est appelé pour chaque objet en fonction de chaque classe qui dérive de VisualElement, vous pouvez utiliser visual State Manager 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 présentés jusqu’à présent, vous pouvez remplacer le nom du groupe « CommonStates » par autre chose, et le programme fonctionnera toujours. Le nom du groupe est simplement une description générale des états de ce groupe. Il est implicitement entendu que les états visuels d’un groupe s’excluent mutuellement : 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 effectuez cet appel à partir du fichier code-behind de votre classe de page.

La page Validation VSM de l’exemple VsmDemos montre comment utiliser Visual State Manager en lien 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 valide », chaque état contenant des VisualState balises.

Si le Entry ne contient pas de numéro de téléphone valide, l’état actuel est « Non valide », de sorte que le Entry a un arrière-plan rose, le second Label est visible et le Button est désactivé :

Validation VSM : validation VSM d’état non valide

Lorsqu’un numéro de téléphone valide est entré, l’état actuel devient « Valide ». le Entry obtient un arrière-plan lime, le second Label disparaît et le Button est maintenant activé :

Validation VSM : validation VSM d’état valide

Le fichier code-behind est responsable de la gestion de l’événement TextChanged à partir de .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 dans le 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 il n’y a aucune référence au nom du groupe d’états visuels, bien qu’il soit référencé dans le XAML comme « ValidationStates » à des fins de clarté.

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

Vous vous demandez peut-être : si le fichier code-behind doit référencer l’objet dans la page qui définit les états visuels, pourquoi le fichier code-behind ne peut-il pas simplement accéder directement à cet objet et à d’autres objets ? C’est sûrement possible. 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 dans 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 aux éléments visuels directement à 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 StateTriggers collection d’un VisualState. Cette collection peut contenir un déclencheur d’état unique ou plusieurs déclencheurs d’état. Un VisualState est appliqué lorsque tous les déclencheurs d’état de la collection sont actifs.

Lorsque vous utilisez des déclencheurs d’état pour contrôler les états visuels, Xamarin.Forms utilisez les règles de priorité suivantes pour déterminer quel déclencheur (et correspondant VisualState) sera actif :

  1. Tout déclencheur qui dérive de StateTriggerBase.
  2. activé AdaptiveTrigger en raison de la MinWindowWidth condition remplie.
  3. activé AdaptiveTrigger en raison de la MinWindowHeight condition remplie.

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 visual State Manager pour la disposition adaptative

Une Xamarin.Forms application s’exécutant sur un téléphone peut généralement être visualisée dans un format 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 : disposition

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

Disposition adaptative VSM :

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

La page Disposition adaptative VSM de l’exemple VsmDemos 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 nommé 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 nommé 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 VerticalOptionsles propriétés , HorizontalOptionset Margin spécifiques aux orientations portrait et paysage.

Le fichier code-behind définit la BindingContext propriété de menuStack pour implémenter Button la commande et joint é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 éléments et , ScrollView puis effectue une boucle à travers les enfants de menuStack pour appeler VisualStateManager.GoToState pour les Button éléments.

Il peut sembler que le fichier code-behind peut gérer les changements d’orientation plus directement en définissant les propriétés des é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 3.0 Visual State Manager