Xamarin.Forms Visual State Manager

Download Sample Stažení ukázky

Pomocí Správce stavu vizuálu můžete provádět změny elementů XAML na základě vizuálních stavů 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 značky popisující, jak Správce stavu vizuálu ovlivňuje vizuály uživatelského rozhraní.

Virtuální počítač představuje koncept vizuálních stavů. Zobrazení Xamarin.Forms , jako Button je například, může mít několik různých vzhledů vizuálů 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 stavy vizuálů 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.

Správce Xamarin.Forms stavu vizuálu definuje jednu skupinu stavů vizuálu s názvem CommonStates s následujícími stavy vizuálu:

  • "Normální"
  • "Zakázáno"
  • "Prioritní"
  • "Vybráno"

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

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

Poznámka:

Xamarin.Forms vývojáři obeznámení s triggery vědí, že triggery mohou 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 ale může být docela matoucí. V historických prostředích založených na jazyce Windows XAML byl představen Správce vizuálního stavu, aby se zmírnit nejasnost vyplývající z kombinací vizuálních stavů. U virtuálního počítače se vizuály ve skupině stavů vizuálu vždy vzájemně vylučují. Aktuální stav je vždy jen jeden stav v každé skupině.

Běžné stavy

Správce vizuálního stavu umožňuje zahrnout do souboru XAML revize, které můžou změnit vzhled zobrazení, pokud je zobrazení normální nebo zakázané nebo má vstupní fokus. Ty se označují jako běž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ími způsoby:

  • Pokud Entry je tato možnost zakázaná Entry , měla by mít růžové pozadí.
  • Normálně Entry by měl mít limetkové pozadí.
  • Pokud Entry má vstupní fokus, měl by se rozbalit na dvojnásobek jeho normální výšky.

Kód VSM můžete připojit k jednotlivým zobrazením nebo ho můžete definovat ve stylu, pokud se vztahuje na více zobrazení. Následující dvě části popisují tyto přístupy.

Revize VSM v zobrazení

Pokud chcete k zobrazení připojit značky Entry VSM, 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 zdvojnásobit velikost textu v objektu Entry.

Potom mezi tyto značky vložte VisualStateManager.VisualStateGroups 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 vlastnostech bindable naleznete v článku Připojené vlastnosti.) Takto 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 pár 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 použít místo toho:

<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ů. Statesje vlastnostVisualStateGroups obsahu, takže můžete zahrnout VisualState značky přímo mezi značkyVisualStateGroup. (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:NameName

<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 VisualStateobsahu , takže je nutné zahrnout značky elementu vlastnosti 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>

Mezi každou dvojici Setters značek teď můžete vložit jeden nebo více Setter objektů. Toto jsou 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í. Všechny vlastnosti odkazované objektem Setter musí být zajištěny vazebnou vlastností.

Revize podobná tomu je 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 k ní je připojena pouze druhá značka virtuálního počítače:

<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é v rámci své Trigger kolekce. To způsobí Entry , že bude zakázána, dokud se něco netypuje 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 s iOSem a Androidem. Implementace Entry UPW nepovoluje nastavení barvy pozadí při zakázání Entry .

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

VSM on View: Normal

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

VSM on View: Focused

Všimněte si, že Entry při získání vstupního fokusu nezachová pozadí limetkového pozadí. Když Správce stavu vizuálu přepíná mezi stavy vizuálu, vlastnosti nastavené předchozím stavem nejsou nastaveny. Mějte na paměti, že se vizuální stavy 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 , aby měl vápno 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 fungovaly správně, VisualStateGroup musí obsahovat VisualState objekty pro všechny stavy v této skupině. Pokud existuje vizuální stav, který neobsahuje žá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 nutné 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 obsahu je SetterValue, 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>

V těchto značkách 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 VSM 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 na jejich vizuální stavy. Všimněte si také, že stav "Prioritní" teď obsahuje sekundu Setter , která každému pozadí vápna dává Entry také, když 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álů tlačítek
CheckBox IsChecked Stavy vizuálu CheckBox
CarouselView DefaultItem, CurrentItem, , PreviousItemNextItem 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, , FocusedSelected 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ů

Vpředchozíchch Je však také možné vytvořit vizuální stavy, které jsou připojeny k jednomu prvku, ale které nastaví vlastnosti na jiných prvcích ve stejném oboru. Vyhnete se tak opakování vizuálních stavů u každého prvku, na kterém stavy pracují.

Typ SetterTargetName vlastnost typu string, která představuje cílový prvek, který Setter bude stav vizuálu 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 TextColor na Label, Property je zadána jako Label.TextColor.

Poznámka:

Všechny vlastnosti odkazované objektem Setter musí být zajištěny vazebnou 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 elementu StackLayout , elementu LabelEntrya a 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>

Kód VSM je připojen k objektu StackLayout. Existují dva vzájemně se vylučující stavy s názvem "Normální" a "Stisknuto", přičemž každý stav obsahuje VisualState značky.

Stav "Normální" je aktivní, když Button není stisknuto, a odpověď na otázku může být zadána:

VSM Setter TargetName: Normal State

Po stisknutí se stav "Stisknuto" změní na Button aktivní:

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 Text mít pojmenovaná Entryentry vlastnost nastavena na Paříž. Výsledkem je proto, že když Button je stisknuto, bude o něco menší a Entry zobrazí Paříž. Po Button vydání se pak škáluje na výchozí hodnotu 1 a Entry zobrazí všechny dříve zadané texty.

Důležité

Cesty k vlastnostem nejsou v současné době podporovány v Setter elementech, které určují TargetName vlastnost.

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

Každá třída odvozená od VisualElement podpory běžných stavů "Normální", "Prioritní" a "Zakázáno". Kromě toho CollectionView třída podporuje "Selected" stav. Třída interně rozpozná, VisualElement kdy se aktivuje nebo zakáže, nebo jestli je fokusovaná, a volá 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 , VisualElementmůžete použít Visual State Manager s libovolným VisualElement objektem reagovat 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 Visual State Manager. V rámci jednoho z dosud zobrazených dvou ukázkových programů můžete změnit název skupiny z commonstates na cokoli jiného a program bude dál fungovat. Název skupiny je pouze obecný popis stavů v této skupině. Implicitně se rozumí tomu, že vizuální stavy v jakékoli skupině se vzájemně vylučují: Jeden stav a vždy je aktuální jenom jeden stav.

Pokud chcete implementovat vlastní vizuální stavy, budete muset volat VisualStateManager.GoToState z kódu. Nejčastěji toto volání provedete 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 Správce stavu vizuálu v souvislosti s ověřováním vstupu. 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>

Kód VSM je připojený k (pojmenované StackLayoutstackLayout). 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 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 je nyní povolen:

VSM Validation: Valid State

Soubor kódu je zodpovědný za zpracování TextChanged události z objektu Entry. 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 k inicializaci stavu. Vždy by měl existovat aktuální stav. Ale nikde v kódu není žádný odkaz na název skupiny stavů vizuálu, i když 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 to, ž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 přistupovat 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 tak, že přistupujete k vizuálním prvkům přímo z kódu.

Triggery vizuálního stavu

Vizuální stavy podporují triggery stavu, což je specializovaná skupina triggerů, které definují podmínky, za kterých VisualState se mají 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 aktivační události stavu v kolekci.

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

  1. Jakákoli aktivační událost, která je odvozena 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 kódu.

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 u těchto různých faktorů formuláře stránky nebo okna zobrazit 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 vizuálního stavu.

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 zobrazovat 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 stavy vizuálů 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.)

Kód VSM se vyskytuje 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 svislá v režimu na šířku.

Čtvrtý oddíl kódu VSM je implicitní styl tlačítek samotných. Tento kód nastaví VerticalOptionsa HorizontalOptionsMargin vlastnosti specifické pro orientaci na výšku a na šířku.

Soubor kódu 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á tyto dva StackLayout prvky a ScrollView potom prochází podřízené menuStack prvky volání VisualStateManager.GoToState prvků ButtonVisualStateManager.GoToState.

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 o Visual State Manageru