Xamarin.Forms Visual State Manager

Download Sample Stažení ukázky

Pomocí Visual State Manageru proveďte změny elementů XAML na základě stavů vizuálů nastavených z kódu.

Visual State Manager (VSM) poskytuje strukturovaný způsob, jak provádět vizuální změny uživatelského rozhraní z kódu. Ve většině případů je uživatelské rozhraní aplikace definováno v JAZYCE XAML a tento XAML obsahuje revize popisující, jak Visual State Manager ovlivňuje vizuály uživatelského rozhraní.

Virtuální počítač zavádí koncept vizuálních stavů. Zobrazení Xamarin.Forms , jako je například, Button může mít několik různých vizuálních vzhledů v závislosti na jeho základním stavu – bez ohledu na to, jestli je zakázaná nebo stisknutá, nebo má fokus vstupu. Toto jsou stavy tlačítka.

Stavy vizuálů se shromažďují ve skupinách stavů vizuálů. Všechny vizuální stavy ve skupině stavů vizuálu se vzájemně vylučují. Vizuální stavy i skupiny stavů vizuálů jsou identifikovány jednoduchými textovými řetězci.

Xamarin.Forms Visual State Manager definuje jednu skupinu stavů vizuálu s názvem CommonStates s následujícími stavy vizuálu:

  • "Normální"
  • Zakázáno
  • "Prioritní"
  • "Selected" (Vybráno)

Tato skupina stavů vizuálu je podporována pro všechny třídy odvozené z VisualElement, což je základní třída pro View a Page.

Můžete také definovat vlastní skupiny stavů vizuálu a stavy vizuálů, jak ukazuje tento článek.

Poznámka

Xamarin.Forms vývojáři, kteří jsou obeznámeni s aktivačními událostmi , vědí, že triggery můžou také provádět změny vizuálů v uživatelském rozhraní na základě změn ve vlastnostech zobrazení nebo spouštění událostí. Použití triggerů k řešení různých kombinací těchto změn se ale může stát poměrně matoucí. Visual State Manager byl zaveden v Windows prostředích založených na XAML, aby se zmírnit nejasnost vyplývající z kombinací vizuálních stavů. U virtuálního počítače se vizuální stavy ve skupině stavů vizuálu vždy vzájemně vylučují. Vždy je aktuální stav pouze jeden stav v každé skupině.

Běžné stavy

Visual State Manager umožňuje zahrnout do souboru XAML revize, které můžou změnit vzhled vizuálu zobrazení, pokud je zobrazení normální nebo zakázané nebo má vstupní fokus. Tyto stavy se označují jako společné státy.

Předpokládejme například, že máte Entry na stránce zobrazení a chcete, aby se vzhled vizuálu Entry změnil následujícím způsobem:

  • Pokud Entry je vypnutý, měl by mít růžové pozadí Entry .
  • Měl Entry by mít normálně vápno.
  • Pokud Entry má vstupní fokus, měl by se zvětšit na dvojnásobek jeho normální výšky.

Kód virtuálního počítače můžete připojit k individuálnímu zobrazení nebo ho můžete definovat ve stylu, pokud se vztahuje na více zobrazení. Následující dvě části popisují tyto přístupy.

Revize virtuálního počítače v zobrazení

Pokud chcete připojit značky virtuálního počítače k Entry zobrazení, nejprve oddělte Entry počáteční a koncové značky:

<Entry FontSize="18">

</Entry>

Má explicitní velikost písma, protože jeden ze stavů použije FontSize vlastnost k zdvojnásobení velikosti textu v souboru Entry.

Dále vložte VisualStateManager.VisualStateGroups značky mezi tyto značky:

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

    </VisualStateManager.VisualStateGroups>
</Entry>

VisualStateGroups je připojená bindable vlastnost definovaná VisualStateManager třídou. (Další informace o připojených svázatelných vlastnostech najdete v článku Připojené vlastnosti.) Tímto způsobem je VisualStateGroups vlastnost připojena k objektu Entry .

Vlastnost VisualStateGroups je typu VisualStateGroupList, což je kolekce VisualStateGroup objektů. VisualStateManager.VisualStateGroups Do značek vložte dvojici VisualStateGroup značek pro každou skupinu stavů vizuálů, které chcete zahrnout:

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

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

Všimněte si, že VisualStateGroup značka má x:Name atribut označující název skupiny. Třída VisualStateGroup definuje Name vlastnost, kterou můžete místo toho použít:

<VisualStateGroup Name="CommonStates">

Můžete použít buď x:Name nebo Name ne oba ve stejném prvku.

Třída VisualStateGroup definuje vlastnost s názvem States, což je kolekce VisualState objektů. States je vlastnostVisualStateGroups obsahu, abyste mohli značky zahrnout VisualState přímo mezi VisualStateGroup značky. (Vlastnosti obsahu jsou popsány v článku Základní syntaxe XAML.)

Dalším krokem je zahrnutí dvojice značek pro každý stav vizuálu v této skupině. Můžete je také identifikovat pomocí x:Name nebo 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 definuje vlastnost s názvem Setters, což je kolekce Setter objektů. Jedná se o stejné Setter objekty, které používáte v objektu Style .

Settersnení vlastnost obsahu , takže je nutné zahrnout značky elementů VisualStatevlastností pro Setters vlastnost:

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

Nyní můžete vložit jeden nebo více Setter objektů mezi každou dvojici Setters značek. Jedná se o Setter objekty, které definují stavy vizuálů popsané výše:

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

Každá Setter značka označuje hodnotu konkrétní vlastnosti, pokud je tento stav aktuální. Každá vlastnost odkazovaná objektem Setter musí být zajištěna vazebnou vlastností.

Značky podobné tomu jsou základem virtuálního počítače na stránce Zobrazení v ukázkovém programu VsmDemos . Stránka obsahuje tři Entry zobrazení, ale pouze druhá má kód virtuálního počítače připojený k němu:

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

Všimněte si, že druhá EntryDataTrigger také součást své Trigger kolekce. To způsobí, že Entry bude zakázána, dokud se něco nenapište do třetí Entry. Tady je stránka při spuštění v iOSu, Androidu a Univerzální platforma Windows (UPW):

VSM on View: Disabled

Aktuální stav vizuálu je "Zakázáno", takže pozadí druhé Entry je růžové na obrazovkách iOS a Androidu. Implementace Entry UPW neumožňuje nastavení barvy pozadí, pokud je zakázaná Entry .

Když do třetího Entryzadáte nějaký text, druhý Entry se přepne do stavu Normální a pozadí je teď vápno:

VSM on View: Normal

Když se dotknete druhého Entry, dostane vstupní fokus. Přepne do stavu Prioritní a rozbalí se na dvojnásobek jeho výšky:

VSM on View: Focused

Všimněte si, že Entry při získání vstupního fokusu se neuchová pozadí vápna. Vzhledem k tomu, že Visual State Manager přepíná mezi stavy vizuálu, vlastnosti nastavené předchozím stavem nejsou nastaveny. Mějte na paměti, že vizuální stavy se vzájemně vylučují. Stav Normální neznamená pouze to, že Entry je povolená. Znamená to, že Entry je povolená a nemá fokus vstupu.

Pokud chcete Entry mít vápenkové pozadí ve stavu Prioritní, přidejte do tohoto vizuálního stavu další Setter :

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

Aby tyto Setter objekty správně fungovaly, VisualStateGroup musí obsahovat VisualState objekty pro všechny stavy v této skupině. Pokud existuje stav vizuálu, který nemá žádné Setter objekty, zahrňte ho přesto jako prázdnou značku:

<VisualState x:Name="Normal" />

Revize Visual State Manageru ve stylu

Často je potřeba sdílet stejné revize Visual State Manageru mezi dvěma nebo více zobrazeními. V tomto případě budete chtít kód vložit do Style definice.

Tady je existující implicitní Style pro Entry prvky na stránce zobrazení virtuálního počítače:

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

Přidejte Setter značky pro připojenou VisualStateManager.VisualStateGroups vlastnost bindable:

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

    </Setter>
</Style>

Vlastnost Setter obsahu je Value, takže hodnotu Value vlastnosti lze zadat přímo v rámci těchto značek. Tato vlastnost je typu VisualStateGroupList:

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

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

Do těchto značek můžete zahrnout jeden z více VisualStateGroup objektů:

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

Zbývající kód virtuálního počítače je stejný jako předtím.

Tady je stránka VSM ve stylu zobrazující kompletní revize virtuálního počítače:

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

Teď všechna Entry zobrazení na této stránce reagují stejným způsobem jako jejich vizuální stavy. Všimněte si také, že stav Prioritní teď obsahuje sekundu Setter , která dává každému Entry vápno pozadí také v případě, že má vstupní fokus:

VSM in Style

Stavy vizuálů v Xamarin.Forms

Následující tabulka uvádí stavy vizuálů, které jsou definovány v Xamarin.Forms:

Třída Stavy Další informace
Button Pressed Stavy vizuálu tlačítka
CheckBox IsChecked Stavy vizuálu CheckBox
CarouselView DefaultItem, CurrentItem, PreviousItem, NextItem Stavy vizuálu CarouselView
ImageButton Pressed Stavy vizuálu ImageButton
RadioButton Checked, Unchecked Stavy vizuálu RadioButton
Switch On, Off Přepnutí stavů vizuálů
VisualElement Normal, Disabled, Focused, Selected Běžné stavy

Každý z těchto stavů je přístupný prostřednictvím skupiny stavů vizuálu s názvem CommonStates.

Kromě toho CollectionView implementuje Selected stav. Další informace naleznete v tématu Změna barvy vybrané položky.

Nastavení stavu u více prvků

V předchozích příkladech byly vizuální stavy připojeny k jednomu elementu a provozovány na nich. Je však také možné vytvořit vizuální stavy, které jsou připojeny k jednomu prvku, ale které nastavují vlastnosti u jiných prvků ve stejném oboru. Tím se zabrání opakování vizuálních stavů u každého prvku, na kterých stavy pracují.

Typ SetterTargetName vlastnost typu string, která představuje cílový prvek, který Setter bude pro vizuální stav manipulovat. TargetName Pokud je vlastnost definována, Setter nastaví Property element definovaný v TargetName :Value

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

V tomto příkladu bude mít pojmenovaná Labellabel vlastnost nastavena na Red.TextColor Při nastavování TargetName vlastnosti je nutné zadat úplnou cestu k vlastnosti v Property. Proto je vlastnost nastavena TextColorLabelna , Property je zadána jako Label.TextColor.

Poznámka

Jakákoli vlastnost odkazovaná objektem Setter musí být zajištěna vazbou vlastnost.

Virtuální počítač se stránkou Setter TargetName v ukázce VsmDemos ukazuje, jak nastavit stav u více prvků z jedné skupiny stavů vizuálu. Soubor XAML se skládá z StackLayout elementu, znaku LabelEntrya :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>

Značka VSM je připojena k sadě StackLayout. Existují dva vzájemně se vylučující stavy s názvem "Normal" a "Pressed", přičemž každý stav obsahuje VisualState značky.

Stav "Normální" je aktivní, když Button není stisknutá, a odpověď na otázku lze zadat:

VSM Setter TargetName: Normal State

Při stisknutí tlačítka se stav "Stisknuto" aktivuje Button :

VSM Setter TargetName: Pressed State

"Pressed" VisualState určuje, že když Button je stisknuto, jeho Scale vlastnost bude změněna z výchozí hodnoty 1 na 0,8. Kromě toho bude mít pojmenovaná EntryentryText vlastnost nastavena na Paříž. Výsledek je proto takový, že když Button je stisknuto, přeškálí se na o něco menší a zobrazí Entry Paříž. Když se pak Button uvolní, přeškálí se na výchozí hodnotu 1 a Entry zobrazí všechny dříve zadané texty.

Důležité

Cesty k vlastnostem nejsou aktuálně podporovány v Setter prvkách, které určují TargetName vlastnost.

Definování vlastních stavů vizuálů

Každá třída, která je odvozena od VisualElement , podporuje běžné stavy Normal, Prioritní a Disabled. Kromě toho CollectionView třída podporuje stav "Selected". Třída interně rozpozná, VisualElement kdy se aktivuje nebo zakáže, nebo jestli je fokusovaná, a zavolá statickou VisualStateManager.GoToState metodu:

VisualStateManager.GoToState(this, "Focused");

Toto je jediný kód Visual State Manageru, který najdete ve VisualElement třídě. Vzhledem k tomu GoToState , že je volána pro každý objekt založený na každé třídě, která je odvozena z VisualElement, můžete použít Visual State Manager s libovolným VisualElement objektem k reakci na tyto změny.

Zajímavé je, že název skupiny stavů vizuálu "CommonStates" není explicitně odkazován v VisualElement. Název skupiny není součástí rozhraní API pro Správce stavu vizuálu. V rámci jednoho ze dvou ukázkových programů zobrazených zatím můžete změnit název skupiny z commonstates na cokoli jiného a program bude fungovat. Název skupiny je pouze obecný popis stavů v této skupině. Implicitně se rozumí tomu, že vizuální stavy v libovolné skupině se vzájemně vylučují: Jeden stav a pouze jeden stav je kdykoli aktuální.

Pokud chcete implementovat vlastní stavy vizuálů, budete muset volat VisualStateManager.GoToState z kódu. Nejčastěji budete volat ze souboru kódu třídy stránky.

Stránka Ověření virtuálního počítače v ukázce VsmDemos ukazuje, jak používat Visual State Manager ve spojení se vstupním ověřováním. Soubor XAML se skládá ze StackLayout dvou Label prvků:EntryButton

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

Značka VSM je připojená StackLayout k (pojmenované stackLayout). Existují dva vzájemně se vylučující stavy s názvem "Valid" a "Invalid", přičemž každý stav obsahuje VisualState značky.

Entry Pokud číslo neobsahuje platné telefonní číslo, aktuální stav je neplatný, takže Entry má růžové pozadí, druhá Label je viditelná a Button je zakázaná:

VSM Validation: Invalid State

Po zadání platného telefonního čísla se aktuální stav změní na Platné. Získá Entry vápno pozadí, druhý Label zmizí a Button teď je povolen:

VSM Validation: Valid State

Soubor s kódem je zodpovědný za zpracování TextChanged události z Entrysouboru . Obslužná rutina používá regulární výraz k určení, jestli je vstupní řetězec platný nebo ne. Metoda v souboru kódu s názvem volá GoToState statickou VisualStateManager.GoToState metodu pro 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);
    }
}

Všimněte si také, že GoToState metoda je volána z konstruktoru pro inicializaci stavu. Vždy by měl existovat aktuální stav. Ale nikde v kódu neexistuje žádný odkaz na název skupiny stavů vizuálu, ačkoli je odkazován v XAML jako "ValidationStates" pro účely srozumitelnosti.

Všimněte si, že soubor kódu za kódem musí vzít v úvahu pouze objekt na stránce, který definuje stavy vizuálu, a volat VisualStateManager.GoToState pro tento objekt. Důvodem je, že oba vizuály cílí na více objektů na stránce.

Možná vás zajímá: Pokud soubor kódu za kódem musí odkazovat na objekt na stránce, která definuje vizuální stavy, proč nemůže soubor kódu jednoduše získat přístup k tomuto a dalším objektům přímo? Určitě by to mohlo. Výhodou použití virtuálního počítače je ale to, že můžete řídit, jak vizuální prvky reagují na jiný stav zcela v XAML, což udržuje veškerý návrh uživatelského rozhraní na jednom místě. Tím se zabrání nastavení vzhledu vizuálu tím, že přistupujete k vizuálním prvkům přímo z kódu.

Triggery stavu vizuálu

Vizuální stavy podporují triggery stavu, což je specializovaná skupina aktivačních událostí, které definují podmínky, za kterých VisualState se má použít.

Aktivační události stavu se přidají do StateTriggers kolekce objektu VisualState. Tato kolekce může obsahovat jednu aktivační událost stavu nebo více aktivačních událostí stavu. A VisualState se použije, když jsou aktivní všechny triggery stavu v kolekci.

Při použití aktivačních událostí stavu k řízení vizuálních stavů pomocí následujících pravidel priority určíte Xamarin.Forms , která aktivační událost (a odpovídající VisualState) bude aktivní:

  1. Všechny aktivační události, které jsou odvozeny od StateTriggerBase.
  2. Aktivovaný AdaptiveTrigger z důvodu MinWindowWidth splnění podmínky.
  3. Aktivovaný AdaptiveTrigger z důvodu MinWindowHeight splnění podmínky.

Pokud je více aktivačních událostí současně aktivních (například dva vlastní triggery), má přednost první aktivační událost deklarovaná v revizích.

Další informace o aktivačních událostech stavu najdete v tématu Aktivační události stavu.

Použití Visual State Manageru pro adaptivní rozložení

Xamarin.Forms Aplikace spuštěná na telefonu se obvykle dá zobrazit v poměru stran na výšku nebo na šířku a Xamarin.Forms program spuštěný na ploše se dá změnit tak, aby předpokládal mnoho různých velikostí a poměrů stran. Dobře navržená aplikace může pro tyto různé faktory formuláře stránky nebo okna zobrazovat svůj obsah odlišně.

Tato technika se někdy označuje jako adaptivní rozložení. Vzhledem k tomu, že adaptivní rozložení zahrnuje pouze vizuály programu, je to ideální aplikace Správce stavu vizuálu.

Jednoduchým příkladem je aplikace, která zobrazuje malou kolekci tlačítek, která ovlivňují obsah aplikace. V režimu na výšku se tato tlačítka můžou zobrazit ve vodorovném řádku v horní části stránky:

VSM Adaptive Layout: Portrait

V režimu na šířku se pole tlačítek může přesunout na jednu stranu a zobrazit ve sloupci:

VSM Adaptive Layout: Landscape

Shora dolů program běží na Univerzální platforma Windows, Androidu a iOSu.

Stránka adaptivního rozložení virtuálního počítače v ukázce VsmDemos definuje skupinu s názvem "OrientationStates" se dvěma vizuálními stavy s názvem "Na výšku" a "Na šířku". (Složitější přístup může být založený na několika různých šířkách stránek nebo oken.)

Značky VSM se vyskytují na čtyřech místech v souboru XAML. Pojmenovaný StackLayoutmainStack obsahuje nabídku i obsah, což je Image prvek. To StackLayout by mělo mít svislou orientaci v režimu na výšku a vodorovnou orientaci v režimu na šířku:

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

Vnitřní ScrollView název menuScroll a pojmenovaná StackLayoutmenuStack implementace nabídky tlačítek. Orientace těchto rozložení je opakem mainStack. Nabídka by měla být vodorovná v režimu na výšku a svisle v režimu na šířku.

Čtvrtá část značek VSM je implicitní styl tlačítek samotných. Tato sada VerticalOptionsznaček a HorizontalOptionsMargin vlastnosti specifické pro orientaci na výšku a na šířku.

Soubor s kódem nastaví BindingContext vlastnost menuStack pro implementaci Button příkazů a také připojí obslužnou rutinu SizeChanged k události stránky:

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

Obslužná rutina SizeChanged volá VisualStateManager.GoToState tyto dva StackLayout prvky a ScrollView potom prochází podřízené prvky menuStack volání VisualStateManager.GoToStateButton prvků.

Může se zdát, že soubor s kódem za kódem může zpracovávat změny orientace přímo nastavením vlastností prvků v souboru XAML, ale Správce vizuálního stavu je rozhodně strukturovanější přístup. Všechny vizuály se uchovávají v souboru XAML, kde se snadněji prověřují, udržují a upravují.

Visual State Manager s Xamarin.University

Xamarin.Forms 3.0 Video visual state manageru