Xamarin.Forms Visual State ManagerXamarin.Forms Visual State Manager

サンプルのダウンロードサンプルのダウンロードDownload Sample Download the sample

Visual State Manager を使用して、コードから設定されたビジュアルの状態に基づいて XAML 要素を変更します。Use the Visual State Manager to make changes to XAML elements based on visual states set from code.

Visual State Manager (VSM) は、コードからユーザーインターフェイスを視覚的に変更できるように構造化された方法を提供します。The Visual State Manager (VSM) provides a structured way to make visual changes to the user interface from code. ほとんどの場合、アプリケーションのユーザーインターフェイスは XAML で定義され、この XAML には、Visual State Manager がユーザーインターフェイスのビジュアルにどのように影響するかを説明するマークアップが含まれます。In most cases, the user interface of the application is defined in XAML, and this XAML includes markup describing how the Visual State Manager affects the visuals of the user interface.

VSM には、視覚的な 状態 の概念が導入されています。The VSM introduces the concept of visual states. などのビューは、その Xamarin.Forms Button 基になる状態に応じて、無効に — なっているか、押されているか、または入力フォーカスがあるかによって、さまざまな視覚外観を持つことができます。A Xamarin.Forms view such as a Button can have several different visual appearances depending on its underlying state — whether it's disabled, or pressed, or has input focus. これは、ボタンの状態です。These are the button's states.

ビジュアル状態は、表示 状態グループ で収集されます。Visual states are collected in visual state groups. ビジュアル状態グループ内のすべての表示状態は、相互に排他的です。All the visual states within a visual state group are mutually exclusive. 視覚的な状態と表示状態の両方のグループは、単純なテキスト文字列によって識別されます。Both visual states and visual state groups are identified by simple text strings.

Xamarin.FormsVisual State Manager は、"CommonStates" という名前の1つの表示状態グループを定義します。表示状態は次のとおりです。The Xamarin.Forms Visual State Manager defines one visual state group named "CommonStates" with the following visual states:

  • "Normal""Normal"
  • 無効に"Disabled"
  • フォーカス"Focused"
  • オフ"Selected"

この表示状態グループは VisualElement 、およびの基本クラスであるから派生したすべてのクラスでサポートされてい View Page ます。This visual state group is supported for all classes that derive from VisualElement, which is the base class for View and Page.

この記事で説明するように、独自のビジュアル状態グループと視覚的な状態を定義することもできます。You can also define your own visual state groups and visual states, as this article will demonstrate.

注意

Xamarin.Forms トリガーを使い慣れている開発 者は、 ビューのプロパティの変更またはイベントの発生に基づいて、ユーザーインターフェイスのビジュアルをトリガーが変更できることに注意してください。Xamarin.Forms developers familiar with triggers are aware that triggers can also make changes to visuals in the user interface based on changes in a view's properties or the firing of events. ただし、これらの変更のさまざまな組み合わせに対応するためにトリガーを使用すると、大幅に混乱する可能性があります。However, using triggers to deal with various combinations of these changes can become quite confusing. 従来、visual State Manager は、視覚的な状態の組み合わせによって生じる混乱を軽減するために、Windows XAML ベースの環境で導入されました。Historically, the Visual State Manager was introduced in Windows XAML-based environments to alleviate the confusion resulting from combinations of visual states. VSM では、表示状態グループ内のビジュアル状態は常に相互に排他的です。With the VSM, the visual states within a visual state group are always mutually exclusive. 各グループの状態は、いつでも現在の状態になります。At any time, only one state in each group is the current state.

一般的な状態Common states

ビジュアル状態マネージャーを使用すると、XAML ファイルにマークアップを含めることができます。これにより、ビューが通常、または無効になっている場合や、入力フォーカスがある場合にビューの外観を変更できます。The Visual State Manager allows you to include markup in your XAML file that can change the visual appearance of a view if the view is normal, or disabled, or has the input focus. これらは 共通の状態 と呼ばれます。These are known as the common states.

たとえば、 Entry ページにビューがあり、の視覚的な外観を次のように変更するとし Entry ます。For example, suppose you have an Entry view on your page, and you want the visual appearance of the Entry to change in the following ways:

  • が無効になっている場合、には Entry ピンク色の背景が必要 Entry です。The Entry should have a pink background when the Entry is disabled.
  • には、 Entry 通常、ライムの背景が必要です。The Entry should have a lime background normally.
  • Entry入力フォーカスがある場合、は通常の高さの2倍になるように展開する必要があります。The Entry should expand to twice its normal height when it has input focus.

個々のビューに VSM マークアップをアタッチすることも、複数のビューに適用する場合はスタイルで定義することもできます。You can attach the VSM markup to an individual view, or you can define it in a style if it applies to multiple views. 次の2つのセクションでは、これらの方法について説明します。The next two sections describe these approaches.

ビューの VSM マークアップVSM markup on a view

VSM マークアップをビューにアタッチするに Entry は、最初にを Entry 開始タグと終了タグに分割します。To attach VSM markup to an Entry view, first separate the Entry into start and end tags:

<Entry FontSize="18">

</Entry>

状態の1つは、プロパティを使用して FontSize 内のテキストのサイズを2倍にするため、明示的なフォントサイズが指定されて Entry います。It's given an explicit font size because one of the states will use the FontSize property to double the size of the text in the Entry.

次に、タグの間にタグを挿入し VisualStateManager.VisualStateGroups ます。Next, insert VisualStateManager.VisualStateGroups tags between those tags:

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

    </VisualStateManager.VisualStateGroups>
</Entry>

VisualStateGroups は、アタッチ可能なバインド可能なプロパティで、クラスによって定義されて VisualStateManager います。VisualStateGroups is an attached bindable property defined by the VisualStateManager class. (アタッチ可能なバインド可能なプロパティの詳細については、「 添付プロパティ」を参照してください)。これは、 VisualStateGroups プロパティがオブジェクトにアタッチされる方法です Entry(For more information on attached bindable properties, see the article Attached properties.) This is how the VisualStateGroups property is attached to the Entry object.

VisualStateGroupsプロパティは VisualStateGroupList 、オブジェクトのコレクションである型です VisualStateGroupThe VisualStateGroups property is of type VisualStateGroupList, which is a collection of VisualStateGroup objects. タグ内に VisualStateManager.VisualStateGroupsVisualStateGroup 含めるビジュアル状態のグループごとにタグのペアを挿入します。Within the VisualStateManager.VisualStateGroups tags, insert a pair of VisualStateGroup tags for each group of visual states you wish to include:

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

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

VisualStateGroupタグには、 x:Name グループの名前を示す属性があることに注意してください。Notice that the VisualStateGroup tag has an x:Name attribute indicating the name of the group. クラスは、 VisualStateGroup Name 代わりに使用できるプロパティを定義します。The VisualStateGroup class defines a Name property that you can use instead:

<VisualStateGroup Name="CommonStates">

またはのいずれかを使用でき x:Name Name ますが、両方を同じ要素内で使用することはできません。You can use either x:Name or Name but not both in the same element.

VisualStateGroupクラスは、オブジェクトのコレクションであるという名前のプロパティを定義し States VisualState ます。The VisualStateGroup class defines a property named States, which is a collection of VisualState objects. States はの コンテンツプロパティ であるため、タグの VisualStateGroups 間に直接タグを含めることができ VisualState VisualStateGroup ます。States is the content property of VisualStateGroups so you can include the VisualState tags directly between the VisualStateGroup tags. (コンテンツプロパティについては、「 基本的な XAML 構文」で説明しています)。(Content properties are discussed in the article Essential XAML Syntax.)

次の手順では、そのグループ内のすべてのビジュアル状態のタグのペアを含めます。The next step is to include a pair of tags for every visual state in that group. これらは、またはを使用して識別することもでき x:Name Name ます。These also can be identified using x:Name or 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 オブジェクトのコレクションであるという名前のプロパティを定義し Setters Setter ます。VisualState defines a property named Setters, which is a collection of Setter objects. これらは、 Setter オブジェクトで使用するオブジェクトと同じ Style です。These are the same Setter objects that you use in a Style object.

Setters はのコンテンツプロパティでは ない ため、プロパティ VisualState のプロパティ要素タグを含める必要があり Setters ます。Setters is not the content property of VisualState, so it is necessary to include property element tags for the Setters property:

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

Setterタグの各ペアの間に1つ以上のオブジェクトを挿入できるようになりました SettersYou can now insert one or more Setter objects between each pair of Setters tags. Setter前に説明した表示状態を定義するオブジェクトを次に示します。These are the Setter objects that define the visual states described earlier:

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

Setter タグは、その状態が current であるときの特定のプロパティの値を示します。Each Setter tag indicates the value of a particular property when that state is current. オブジェクトによって参照 Setter されるプロパティは、バインド可能なプロパティによってサポートされている必要があります。Any property referenced by a Setter object must be backed by a bindable property.

これに似たマークアップは、 VsmDemos サンプルプログラムの [ビューの VSM ] ページの基礎となります。Markup similar to this is the basis of the VSM on View page in the VsmDemos sample program. このページには3つのビューが含まれてい Entry ますが、2つ目のビューには、VSM マークアップがアタッチされています。The page includes three Entry views, but only the second one has the VSM markup attached to it:

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

2番目のは、 Entry DataTrigger コレクションの一部としても含まれていることに注意して Trigger ください。Notice that the second Entry also has a DataTrigger as part of its Trigger collection. これにより、 Entry 3 番目のに何かが入力されるまで、が無効になり Entry ます。This causes the Entry to be disabled until something is typed into the third Entry. IOS、Android、ユニバーサル Windows プラットフォーム (UWP) で実行される起動時のページを次に示します。Here's the page at startup running on iOS, Android, and the Universal Windows Platform (UWP):

ビューの VSM: 無効VSM on View: Disabled

現在の表示状態は "無効" です。そのため、iOS と Android の画面では、2番目の背景 Entry がピンク色になります。The current visual state is "Disabled" so the background of the second Entry is pink on the iOS and Android screens. の UWP 実装では Entry 、が無効になっている場合に背景色を設定することはできません EntryThe UWP implementation of Entry does not allow setting the background color when the Entry is disabled.

3番目の部分にテキストを入力すると、 Entry 2 番目のは Entry "通常" の状態に切り替わり、背景は "ライム" になります。When you enter some text into the third Entry, the second Entry switches into the "Normal" state, and the background is now lime:

ビューの VSM: 通常VSM on View: Normal

2番目のをタッチすると、 Entry 入力フォーカスが取得されます。When you touch the second Entry, it gets the input focus. "フォーカスされた" 状態に切り替わり、2倍の高さに拡張されます。It switches to the "Focused" state and expands to twice its height:

ビューの VSM: フォーカスされるVSM on View: Focused

は、 Entry 入力フォーカスを取得するときに、ライムの背景を保持しないことに注意してください。Notice that the Entry does not retain the lime background when it gets the input focus. ビジュアル状態マネージャーは、表示状態を切り替えるときに、以前の状態に設定されたプロパティの設定が解除されます。As the Visual State Manager switches between the visual states, the properties set by the previous state are unset. 視覚的な状態は相互に排他的であることに注意してください。Keep in mind that the visual states are mutually exclusive. "Normal" 状態は、が有効になっているだけではありません EntryThe "Normal" state does not mean solely that the Entry is enabled. は、 Entry が有効になっていて、入力フォーカスがないことを意味します。It means that the Entry is enabled and does not have input focus.

が "フォーカスされた Entry " 状態でライムの背景を持つようにするには、そのビジュアル状態に別の背景を追加し Setter ます。If you want the Entry to have a lime background in the "Focused" state, add another Setter to that visual state:

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

これらのオブジェクトが Setter 正常に機能するためには、 VisualStateGroup VisualState そのグループ内のすべての状態のオブジェクトがに含まれている必要があります。In order for these Setter objects to work properly, a VisualStateGroup must contain VisualState objects for all the states in that group. オブジェクトが含まれていないビジュアル状態がある場合は Setter 、空のタグとして追加します。If there is a visual state that does not have any Setter objects, include it anyway as an empty tag:

<VisualState x:Name="Normal" />

スタイルのビジュアル状態マネージャーマークアップVisual State Manager markup in a style

多くの場合、2つ以上のビューで同じ Visual State Manager マークアップを共有する必要があります。It's often necessary to share the same Visual State Manager markup among two or more views. この場合は、定義にマークアップを配置する必要が Style あります。In this case, you'll want to put the markup in a Style definition.

次に、 Style Entry VSM On ビュー ページの要素に対する既存の暗黙的な例を示します。Here's the existing implicit Style for the Entry elements in the VSM On View page:

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

Setterアタッチ可能なバインド可能なプロパティのタグを追加し VisualStateManager.VisualStateGroups ます。Add Setter tags for the VisualStateManager.VisualStateGroups attached bindable property:

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

    </Setter>
</Style>

のコンテンツプロパティ SetterValue であるため、プロパティの値は、 Value これらのタグ内で直接指定できます。The content property for Setter is Value, so the value of the Value property can be specified directly within those tags. このプロパティの型は VisualStateGroupList 次のとおりです。That property is of type VisualStateGroupList:

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

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

これらのタグ内には、次のオブジェクトのいずれかを含めることができ VisualStateGroup ます。Within those tags you can include one of more VisualStateGroup objects:

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

VSM マークアップの残りの部分は、以前と同じです。The remainder of the VSM markup is the same as before.

次に、vsm の完全なマークアップを示す vsm のスタイルページを 示します。Here's the VSM in Style page showing the complete VSM markup:

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

これで、 Entry このページのすべてのビューが、表示状態と同じように応答するようになりました。Now all the Entry views on this page respond the same way to their visual states. また、"フォーカスされた" 状態には、 Setter Entry 入力フォーカスがあるときに、それぞれの背景をライムにするための2番目のが含まれるようになりました。Notice also that the "Focused" state now includes a second Setter that gives each Entry a lime background also when it has input focus:

VSM (スタイル)VSM in Style

表示状態 Xamarin.FormsVisual states in Xamarin.Forms

次の表に、で定義されている表示状態の一覧を示し Xamarin.Forms ます。The following table lists the visual states that are defined in Xamarin.Forms:

インスタンスClass 状態States 詳細情報More Information
Button Pressed ボタンの表示状態Button visual states
CheckBox IsChecked チェックボックスの表示状態CheckBox visual states
CarouselView DefaultItem, CurrentItem, PreviousItem, NextItemDefaultItem, CurrentItem, PreviousItem, NextItem CarouselView の視覚的状態CarouselView visual states
ImageButton Pressed ImageButton ビジュアルの状態ImageButton visual states
RadioButton Checked, UncheckedChecked, Unchecked RadioButton の表示状態RadioButton visual states
Switch On, OffOn, Off ビジュアル状態の切り替えSwitch visual states
VisualElement Normal, Disabled, Focused, SelectedNormal, Disabled, Focused, Selected 一般的な状態Common states

これらの各状態には、という名前の表示状態グループを使用してアクセスでき CommonStates ます。Each of these states can be accessed through the visual state group named CommonStates.

さらに、は CollectionView 状態を実装し Selected ます。In addition, the CollectionView implements the Selected state. 詳細については、「 選択した項目の色を変更する」を参照してください。For more information, see Change selected item color.

複数の要素の状態を設定するSet state on multiple elements

前の例では、ビジュアルの状態が1つの要素にアタッチされ、操作されていました。In the previous examples, visual states were attached to and operated on single elements. ただし、1つの要素に関連付けられているが、同じスコープ内の他の要素にプロパティを設定する表示状態を作成することもできます。However, it's also possible to create visual states that are attached to a single element, but that set properties on other elements within the same scope. これにより、状態が動作する各要素に対して視覚的状態を繰り返す必要がなくなります。This avoids having to repeat visual states on each element the states operate on.

Setter型には、 TargetName 型のプロパティがあり string ます。これは、ビジュアル状態のが操作するターゲット要素を表し Setter ます。The Setter type has a TargetName property, of type string, that represents the target element that the Setter for a visual state will manipulate. プロパティが定義されると、 TargetNameSetter Property で定義されている要素のをに設定し TargetName Value ます。When the TargetName property is defined, the Setter sets the Property of the element defined in TargetName to Value:

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

この例では、 Label という名前のの label プロパティがに設定されてい TextColor Red ます。In this example, a Label named label will have its TextColor property set to Red. プロパティを設定するときは、 TargetName のプロパティへの完全なパスを指定する必要があり Property ます。When setting the TargetName property you must specify the full path to the property in Property. したがって、でプロパティを設定するに TextColor Label は、を Property として指定し Label.TextColor ます。Therefore, to set the TextColor property on a Label, Property is specified as Label.TextColor.

注意

オブジェクトによって参照 Setter されるプロパティは、バインド可能なプロパティによってサポートされている必要があります。Any property referenced by a Setter object must be backed by a bindable property.

VsmDemos サンプルの [ Setter with Setter TargetName ] ページでは、1つのビジュアル状態グループから複数の要素の状態を設定する方法を示します。The VSM with Setter TargetName page in the VsmDemos sample shows how to set state on multiple elements, from a single visual state group. XAML ファイルは、 StackLayout Label 要素、、およびを含むで構成され Entry Button ます。The XAML file consists of a StackLayout containing a Label element, an Entry, and 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>

VSM マークアップはにアタッチされ StackLayout ます。VSM markup is attached to the StackLayout. "Normal" と "押された" という名前の2つの相互排他的な状態があり、各状態にはタグが含まれてい VisualState ます。There are two mutually-exclusive states, named "Normal" and "Pressed", with each state containing VisualState tags.

が押されていない場合は "Normal" 状態がアクティブになり、 Button 質問に対する応答を入力できます。The "Normal" state is active when the Button isn't pressed, and a response to the question can be entered:

VSM Setter TargetName: 通常の状態VSM Setter TargetName: Normal State

が押されると、"押された" 状態がアクティブになり Button ます。The "Pressed" state becomes active when the Button is pressed:

VSM Setter TargetName: 押された状態VSM Setter TargetName: Pressed State

"押された" は、 VisualState が押されると、 Button その Scale プロパティが既定値の1から0.8 に変更されることを指定します。The "Pressed" VisualState specifies that when the Button is pressed, its Scale property will be changed from the default value of 1 to 0.8. また、という名前のでは、 Entry entry Text プロパティがパリに設定されます。In addition, the Entry named entry will have its Text property set to Paris. 結果として、が押されると、 Button スケールが少し小さくなり、に Entry パリが表示されます。Therefore, the result is that when the Button is pressed it's rescaled to be slightly smaller, and the Entry displays Paris. その後、 Button が解放されると、スケールは既定値の1になり、に Entry 以前に入力したテキストが表示されます。Then, when the Button is released it's rescaled to its default value of 1 ,and the Entry displays any previously entered text.

重要

プロパティパスは Setter 、現在、プロパティを指定する要素ではサポートされていません TargetNameProperty paths are currently unsupported in Setter elements that specify the TargetName property.

独自の視覚的状態を定義するDefine your own visual states

から派生するすべてのクラス VisualElement は、共通の状態 "Normal"、"フォーカスされた"、および "Disabled" をサポートしています。Every class that derives from VisualElement supports the common states "Normal", "Focused", and "Disabled". また、クラスは CollectionView "Selected" 状態をサポートします。In addition, the CollectionView class supports the "Selected" state. 内部的には、クラスは、 VisualElement 有効または無効になったとき、またはフォーカスまたは見るされたことを検出し、static [ VisualStateManager.GoToState ] (xref: を呼び出します Xamarin.Forms 。VisualStateManager GoToState ( Xamarin.Forms .VisualElement, System.string) メソッド:Internally, the VisualElement class detects when it's becoming enabled or disabled, or focused or unfocused, and calls the static VisualStateManager.GoToState method:

VisualStateManager.GoToState(this, "Focused");

これは、クラスで見つかった唯一の表示状態マネージャーコードです VisualElementThis is the only Visual State Manager code that you'll find in the VisualElement class. GoToStateは、から派生したすべてのクラスに基づいてすべてのオブジェクトに対して呼び出されるので VisualElement 、Visual State Manager を任意のオブジェクトと共に使用して、これらの変更に応答することができ VisualElement ます。Because GoToState is called for every object based on every class that derives from VisualElement, you can use the Visual State Manager with any VisualElement object to respond to these changes.

興味深いことに、ビジュアル状態グループ "CommonStates" の名前はで明示的に参照されていません VisualElementInterestingly, the name of the visual state group "CommonStates" is not explicitly referenced in VisualElement. グループ名は、Visual State Manager の API の一部ではありません。The group name is not part of the API for the Visual State Manager. これまでに示した2つのサンプルプログラムのいずれかで、グループの名前を "CommonStates" から他のものに変更することができ、プログラムは引き続き機能します。Within one of the two sample program shown so far, you can change the name of the group from "CommonStates" to anything else, and the program will still work. グループ名は、そのグループ内の状態の一般的な説明にすぎません。The group name is merely a general description of the states in that group. すべてのグループのビジュアル状態は相互に排他的であることが暗黙的に認識されます。1つの状態であり、いつでも1つの状態のみが最新です。It is implicitly understood that the visual states in any group are mutually exclusive: One state and only one state is current at any time.

独自のビジュアル状態を実装する場合は、コードからを呼び出す必要があり VisualStateManager.GoToState ます。If you want to implement your own visual states, you'll need to call VisualStateManager.GoToState from code. ほとんどの場合、この呼び出しはページクラスの分離コードファイルから行います。Most often you'll make this call from the code-behind file of your page class.

VsmDemos サンプルの VSM 検証 ページでは、入力検証と共に Visual State Manager を使用する方法を示しています。The VSM Validation page in the VsmDemos sample shows how to use the Visual State Manager in connection with input validation. XAML ファイルは、、 StackLayout 、およびという2つの要素で構成され Label Entry Button ます。The XAML file consists of a StackLayout containing two Label elements, an Entry, and a 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>

VSM マークアップは、 StackLayout (という名前の) にアタッチされ stackLayout ます。VSM markup is attached to the StackLayout (named stackLayout). "Valid" と "Invalid" という名前の2つの相互排他的な状態があり、各状態にはタグが含まれてい VisualState ます。There are two mutually-exclusive states, named "Valid" and "Invalid", with each state containing VisualState tags.

Entry 有効な電話番号が含まれていない場合、現在の状態は "無効" になります。したがって、は Entry ピンク色の背景を持ち、2番目のは表示され、は無効になり Label Button ます。If the Entry does not contain a valid phone number, then the current state is "Invalid", and so the Entry has a pink background, the second Label is visible, and the Button is disabled:

VSM 検証: 状態が無効ですVSM Validation: Invalid State

有効な電話番号を入力すると、現在の状態は "有効" になります。When a valid phone number is entered, then the current state becomes "Valid". は、 Entry ライムの背景を取得し、2番目のが消え、 Label Button が有効になりました。The Entry gets a lime background, the second Label disappears, and the Button is now enabled:

VSM 検証: 有効な状態VSM Validation: Valid State

分離コードファイルは、からのイベントを処理し TextChanged Entry ます。The code-behind file is responsible for handling the TextChanged event from the Entry. ハンドラーは、正規表現を使用して、入力文字列が有効かどうかを判断します。The handler uses a regular expression to determine if the input string is valid or not. という分離コードファイル内のメソッドは、 GoToState の静的 VisualStateManager.GoToState メソッドを呼び出し stackLayout ます。The method in the code-behind file named GoToState calls the static VisualStateManager.GoToState method for 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);
    }
}

GoToStateメソッドは、状態を初期化するためにコンストラクターから呼び出されることにも注意してください。Notice also that the GoToState method is called from the constructor to initialize the state. 常に現在の状態になっている必要があります。There should always be a current state. しかし、コードには、表示状態グループの名前への参照が含まれていますが、わかりやすくするために、XAML では "ValidationStates" として参照されています。But nowhere in the code is there any reference to the name of the visual state group, although it's referenced in the XAML as "ValidationStates" for purposes of clarity.

分離コードファイルでは、表示状態を定義するページ上のオブジェクトと、このオブジェクトを呼び出す必要があることに注意して VisualStateManager.GoToState ください。Notice that the code-behind file only needs to take account of the object on the page that defines the visual states, and to call VisualStateManager.GoToState for this object. これは、両方の表示状態がページ上の複数のオブジェクトを対象としているためです。This is because both visual states target multiple objects on the page.

コードビハインドファイルが視覚的な状態を定義するページのオブジェクトを参照する必要がある場合は、分離コードファイルがこのオブジェクトと他のオブジェクトに直接アクセスできないのはなぜですか。You might wonder: If the code-behind file must reference the object on the page that defines the visual states, why can't the code-behind file simply access this and other objects directly? 確かにできます。It surely could. ただし、VSM を使用する利点は、すべての UI デザインを1つの場所に保持することで、ビジュアル要素がどのような状態になるかを XAML 全体で制御できることです。However, the advantage of using the VSM is that you can control how visual elements react to different state entirely in XAML, which keeps all of the UI design in one location. これにより、分離コードからビジュアル要素に直接アクセスすることで、視覚的な外観を設定することが回避されます。This avoids setting visual appearance by accessing visual elements directly from the code-behind.

ビジュアル状態のトリガーVisual state triggers

表示状態は、を適用する条件を定義する特殊なトリガーグループである状態トリガーをサポート VisualState します。Visual states support state triggers, which are a specialized group of triggers that define the conditions under which a VisualState should be applied.

状態トリガーは、VisualStateStateTriggers コレクションに追加されます。State triggers are added to the StateTriggers collection of a VisualState. このコレクションには、1 つの状態トリガーを含めることも、複数の状態トリガーを含めることもできます。This collection can contain a single state trigger, or multiple state triggers. コレクション内のいずれかの状態トリガーがアクティブになっていると、VisualState が適用されます。A VisualState will be applied when any state triggers in the collection are active.

状態トリガーを使用してビジュアルの状態を制御する場合、Xamarin.Forms では、アクティブにするトリガー (および対応する VisualState) を決定するために、次の優先順位規則が使用されます。When using state triggers to control visual states, Xamarin.Forms uses the following precedence rules to determine which trigger (and corresponding VisualState) will be active:

  1. StateTriggerBase から派生したトリガー。Any trigger that derives from StateTriggerBase.
  2. MinWindowWidth 条件の適用によってアクティブにされた AdaptiveTriggerAn AdaptiveTrigger activated due to the MinWindowWidth condition being met.
  3. MinWindowHeight 条件の適用によってアクティブにされた AdaptiveTriggerAn AdaptiveTrigger activated due to the MinWindowHeight condition being met.

複数のトリガーが同時にアクティブにされた場合 (たとえば、2 つのカスタム トリガー)、マークアップで最初に宣言されたトリガーが優先されます。If multiple triggers are simultaneously active (for example, two custom triggers) then the first trigger declared in the markup takes precedence.

状態トリガーの詳細については、「状態トリガー」を参照してください。For more information about state triggers, see State triggers.

アダプティブレイアウトでのビジュアル状態マネージャーの使用Use the Visual State Manager for adaptive layout

Xamarin.Formsスマートフォンで実行されるアプリケーションは、通常、縦または横の縦横比で表示でき、 Xamarin.Forms デスクトップで実行されているプログラムのサイズを変更して、さまざまなサイズや縦横比を想定することができます。A Xamarin.Forms application running on a phone can usually be viewed in a portrait or landscape aspect ratio, and a Xamarin.Forms program running on the desktop can be resized to assume many different sizes and aspect ratios. 適切にデザインされたアプリケーションでは、さまざまなページまたはウィンドウのフォームファクターに応じてコンテンツが異なる方法で表示されることがあります。A well-designed application might display its content differently for these various page or window form factors.

この手法は、 アダプティブレイアウト とも呼ばれます。This technique is sometimes known as adaptive layout. アダプティブレイアウトでは、プログラムのビジュアルのみが必要であるため、ビジュアル状態マネージャーの理想的なアプリケーションです。Because adaptive layout solely involves a program's visuals, it is an ideal application of the Visual State Manager.

単純な例として、アプリケーションのコンテンツに影響を与える小さなボタンのコレクションを表示するアプリケーションがあります。A simple example is an application that displays a small collection of buttons that affect the application's content. 縦モードでは、これらのボタンはページ上部の水平方向の行に表示されることがあります。In portrait mode, these buttons might be displayed in a horizontal row on the top of the page:

VSM アダプティブレイアウト: 縦VSM Adaptive Layout: Portrait

横モードでは、ボタンの配列が一方向に移動され、列に表示されることがあります。In landscape mode, the array of buttons might be moved to one side, and displayed in a column:

VSM アダプティブレイアウト: 横VSM Adaptive Layout: Landscape

このプログラムは、上から下に、ユニバーサル Windows プラットフォーム、Android、および iOS で実行されています。From top to bottom, the program is running on the Universal Windows Platform, Android, and iOS.

VsmDemosサンプルの VSM アダプティブレイアウト ページでは、"縦" と "横" という名前の2つの表示状態を持つ "OrientationStates" という名前のグループを定義します。The VSM Adaptive Layout page in the VsmDemos sample defines a group named "OrientationStates" with two visual states named "Portrait" and "Landscape". (より複雑な方法は、複数の異なるページやウィンドウの幅に基づいている場合があります)。(A more complex approach might be based on several different page or window widths.)

VSM マークアップは、XAML ファイル内の4つの場所で実行されます。VSM markup occurs in four places in the XAML file. StackLayoutという名前のには、要素である mainStack メニューとコンテンツの両方が含まれてい Image ます。The StackLayout named mainStack contains both the menu and the content, which is an Image element. StackLayout モードの垂直方向と横向きモードの水平方向を持つ必要があります。This StackLayout should have a vertical orientation in portrait mode and a horizontal orientation in landscape mode:

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

という ScrollView 名前のとは、 menuScroll StackLayout menuStack ボタンのメニューを実装します。The inner ScrollView named menuScroll and the StackLayout named menuStack implement the menu of buttons. これらのレイアウトの向きは、の反対です mainStackThe orientation of these layouts is opposite of mainStack. メニューは縦モードで水平にし、横モードで垂直にする必要があります。The menu should be horizontal in portrait mode and vertical in landscape mode.

VSM マークアップの4番目のセクションは、ボタン自体の暗黙的なスタイルです。The fourth section of VSM markup is in an implicit style for the buttons themselves. このマークアップは VerticalOptionsHorizontalOptions Margin 縦と横の向きに固有の、、およびの各プロパティを設定します。This markup sets VerticalOptions, HorizontalOptions, and Margin properties specific to the portrait and landscape orientations.

分離コードファイルは、 BindingContext menuStack コマンド実行を実装するためにのプロパティを設定 Button し、さらにページのイベントにハンドラーをアタッチし SizeChanged ます。The code-behind file sets the BindingContext property of menuStack to implement Button commanding, and also attaches a handler to the SizeChanged event of the 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; }
}

この SizeChanged ハンドラーは、 VisualStateManager.GoToState 2 つの要素および要素を呼び出し、の子をループ処理して StackLayout ScrollView menuStack VisualStateManager.GoToState 要素を呼び出し Button ます。The SizeChanged handler calls VisualStateManager.GoToState for the two StackLayout and ScrollView elements, and then loops through the children of menuStack to call VisualStateManager.GoToState for the Button elements.

XAML ファイルの要素のプロパティを設定することによって、分離コードファイルで向きの変更をより直接的に処理できるように見えるかもしれませんが、視覚的な状態マネージャーは、明らかに構造化されたアプローチです。It may seem as if the code-behind file can handle orientation changes more directly by setting properties of elements in the XAML file, but the Visual State Manager is definitely a more structured approach. すべてのビジュアルは XAML ファイルに保持され、簡単に調査、保守、および変更できます。All the visuals are kept in the XAML file, where they become easier to examine, maintain, and modify.

Visual State Manager と Xamarin 大学Visual State Manager with Xamarin.University

Xamarin.Forms 3.0 Visual State Manager ビデオXamarin.Forms 3.0 Visual State Manager video