トリガー

Browse sample.サンプルを参照する

.NET Multi-Platform App UI (.NET MAUI) のトリガーを使用すると、イベントまたはデータの変更に基づいてコントロールの外観を変更するアクションを、XAML で宣言として表すことができます。 また、トリガーの特殊なグループである状態トリガーでは、VisualState を適用する条件を定義できます。

トリガーは、コントロールの Triggers コレクションに直接割り当てることも、ページレベルまたはアプリレベルのリソース ディクショナリに追加して複数のコントロールに適用することもできます。

プロパティ トリガー

Trigger は、指定のプロパティが指定の条件を満たすとプロパティ値を適用するかアクションを実行するトリガーを表します。

次の例は、フォーカスを受け取ると Entry 背景色を変更する Trigger を示しています。

<Entry Placeholder="Enter name">
    <Entry.Triggers>
        <Trigger TargetType="Entry"
                 Property="IsFocused"
                 Value="True">
            <Setter Property="BackgroundColor"
                    Value="Yellow" />
            <!-- Multiple Setter elements are allowed -->
        </Trigger>
    </Entry.Triggers>
</Entry>

トリガーの宣言では、以下を指定します。

  • TargetType: トリガーを適用するコントロールの種類です。
  • Property: 監視対象となる、コントロールのプロパティです。
  • Value: 監視対象のプロパティがこの値になったら、トリガーがアクティブになります。
  • Setter: トリガー条件が満たされたときに適用される Setter 要素のコレクションです。

さらに、オプションの EnterActions および ExitActions コレクションを指定できます。 詳細については、「EnterActions と ExitActions」をご覧ください。

スタイルを使用してトリガーを適用する

トリガーは、コントロール、ページ、またはアプリケーションの ResourceDictionaryStyle 宣言に追加することもできます。 次の例では、ページ上のすべての Entry コントロールに暗黙的なスタイルを宣言しています。

<ContentPage.Resources>
    <Style TargetType="Entry">
        <Style.Triggers>
            <Trigger TargetType="Entry"
                     Property="IsFocused"
                     Value="True">
                <Setter Property="BackgroundColor"
                        Value="Yellow" />
                <!-- Multiple Setter elements are allowed -->
            </Trigger>
        </Style.Triggers>
    </Style>
</ContentPage.Resources>

データ トリガー

DataTrigger は、バインドされたデータが指定の条件を満たすとプロパティ値を適用するかアクションを実行するトリガーを表します。 指定された条件を監視するために、Binding マークアップ拡張が使用されます。

次の例は、Entry が空の場合に Button を無効にする DataTrigger を示しています。

<Entry x:Name="entry"
       Text=""
       Placeholder="Enter text" />
<Button Text="Save">
    <Button.Triggers>
        <DataTrigger TargetType="Button"
                     Binding="{Binding Source={x:Reference entry},
                                       Path=Text.Length}"
                     Value="0">
            <Setter Property="IsEnabled"
                    Value="False" />
            <!-- Multiple Setter elements are allowed -->
        </DataTrigger>
    </Button.Triggers>
</Button>

この例では、Entry の長さが 0 になると、トリガーがアクティブになります。

ヒント

Path=Text.Length の評価時には、ターゲット プロパティ (例: Text="") の既定値を常に指定します。指定しない場合は null になり、トリガーが想定どおりに動作しなくなるからです。

さらに、オプションの EnterActions および ExitActions コレクションを指定できます。 詳細については、「EnterActions と ExitActions」をご覧ください。

Event triggers (イベント トリガー)

EventTrigger は、イベントに応答して一連のアクションを適用するトリガーを表します。 Trigger とは異なり、EventTrigger には状態の終了という概念がないので、イベントの発生につながった条件が真でなくなったら、アクションは元に戻りません。

EventTrigger では、次のように Event プロパティを設定すればよいだけです。

<EventTrigger Event="TextChanged">
    <local:NumericValidationTriggerAction />
</EventTrigger>

この例では、Setter 要素はありません。 代わりに、NumericalValidationTriggerAction オブジェクトがあります。

Note

イベント トリガーでは EnterActionsExitActions をサポートしていません。

トリガー アクションは、次のように実装する必要があります。

  • トリガーの適用対象であるコントロールの種類に対応するジェネリック パラメーターを使用してジェネリック TriggerAction<T> クラスを実装します。 VisualElement などのクラスを使用して、さまざまなコントロールで動作するトリガー アクションを記述したり、Entry などのコントロールの種類を指定したりできます。
  • Invoke メソッドをオーバーライドします。 このメソッドは、トリガー イベントが発生するたびに呼び出されます。
  • 必要に応じて、トリガーを宣言するときに XAML で設定できるプロパティを公開します。

次の例は、NumericValidationTriggerAction クラスを示しています。

public class NumericValidationTriggerAction : TriggerAction<Entry>
{
    protected override void Invoke(Entry entry)
    {
        double result;
        bool isValid = Double.TryParse(entry.Text, out result);
        entry.TextColor = isValid ? Colors.Black : Colors.Red;
    }
}

警告

ResourceDictionary でトリガーを共有する場合は、注意してください。 1 つのインスタンスが複数のコントロールで共有されるので、一度構成された状態はすべてのコントロールに適用されます。

マルチトリガー

MultiTrigger は、一連の条件が満たされたるとプロパティ値を適用するかアクションを実行するトリガーを表します。 Setter オブジェクトが適用されるには、すべての条件が満たされる必要があります。

次の例は、2 つの Entry オブジェクトにバインドする MultiTrigger を示したものです。

<Entry x:Name="email"
       Text="" />
<Entry x:Name="phone"
       Text="" />
<Button Text="Save">
    <Button.Triggers>
        <MultiTrigger TargetType="Button">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding Source={x:Reference email},
                                            Path=Text.Length}"
                                  Value="0" />
                <BindingCondition Binding="{Binding Source={x:Reference phone},
                                            Path=Text.Length}"
                                  Value="0" />
            </MultiTrigger.Conditions>
            <Setter Property="IsEnabled" Value="False" />
            <!-- multiple Setter elements are allowed -->
        </MultiTrigger>
    </Button.Triggers>
</Button>

さらに、MultiTrigger.Conditions コレクションには PropertyCondition オブジェクトを含めることもできます。

<PropertyCondition Property="Text"
                   Value="OK" />

EnterActions と ExitActions

トリガーが発生した際に変更を実装する別の方法は、EnterActionsExitActions コレクションを指定して、TriggerAction<T> の実装を作成することです。

IList<TriggerAction> 型の EnterActions コレクションは、トリガー条件が満たされたときに呼び出されるコレクションを定義します。 IList<TriggerAction> 型の ExitActions コレクションは、トリガー条件が満たされなくなった後に呼び出されるコレクションを定義します。

Note

EnterActions コレクションと ExitActions コレクションで定義されている TriggerAction オブジェクトは、EventTrigger クラスによって無視されます。

次の例は、EnterActionExitAction を指定するプロパティ トリガーを示しています。

<Entry Placeholder="Enter job title">
    <Entry.Triggers>
        <Trigger TargetType="Entry"
                 Property="Entry.IsFocused"
                 Value="True">
            <Trigger.EnterActions>
                <local:FadeTriggerAction StartsFrom="0" />
            </Trigger.EnterActions>

            <Trigger.ExitActions>
                <local:FadeTriggerAction StartsFrom="1" />
            </Trigger.ExitActions>
        </Trigger>
    </Entry.Triggers>
</Entry>

トリガー アクションは次のように実装する必要があります。

  • トリガーの適用対象であるコントロールの種類に対応するジェネリック パラメーターを使用してジェネリック TriggerAction<T> クラスを実装します。 VisualElement などのクラスを使用してさまざまなコントロールで動作するトリガー アクションを記述したり、コントロールのタイプ (Entry など) を指定したりできます。
  • Invoke メソッドをオーバーライドします。 このメソッドは、トリガー イベントが発生するたびに呼び出されます。
  • 必要に応じて、トリガーを宣言する際に、XAML で設定できるプロパティを公開します。

次の例は、FadeTriggerAction クラスを示しています。

public class FadeTriggerAction : TriggerAction<VisualElement>
{
    public int StartsFrom { get; set; }

    protected override void Invoke(VisualElement sender)
    {
        sender.Animate("FadeTriggerAction", new Animation((d) =>
        {
            var val = StartsFrom == 1 ? d : 1 - d;
            sender.BackgroundColor = Color.FromRgb(1, val, 1);
        }),
        length: 1000, // milliseconds
        easing: Easing.Linear);
    }
}

Note

トリガーでは、Setter オブジェクトだけでなく、EnterActionsExitActions のオブジェクトも提供できますが、Setter オブジェクトはすぐに呼び出されることに注意してください (EnterActionExitAction が完了するのを待機しません)。

状態トリガー

状態トリガーは VisualState が適用される条件を定義するための特殊なトリガーのグループです。

状態トリガーは、VisualStateStateTriggers コレクションに追加されます。 このコレクションには、1 つの状態トリガーを含めることも、複数の状態トリガーを含めることもできます。 コレクション内のいずれかの状態トリガーがアクティブになっていると、VisualState が適用されます。

状態トリガーを使用してビジュアルの状態を制御する場合、.NET MAUI では、次の優先順位規則を使用して、アクティブにするトリガー (VisualState に対応する) を決定します。

  1. StateTriggerBase から派生したトリガー。
  2. MinWindowWidth 条件の適用によってアクティブにされた AdaptiveTrigger
  3. MinWindowHeight 条件の適用によってアクティブにされた AdaptiveTrigger

複数のトリガーが同時にアクティブにされた場合 (たとえば、2 つのカスタム トリガー)、マークアップで最初に宣言されたトリガーが優先されます。

Note

状態トリガーは、Style で設定することも、要素で直接設定することもできます。

表示状態の詳細については、「表示状態」をご覧ください。

状態トリガー

StateTriggerBase クラスから派生する StateTrigger クラスには、バインド可能な IsActive プロパティがあります。 StateTrigger では、IsActive プロパティの値が変更されたときに VisualState の変更がトリガーされます。

すべての状態トリガーの基底クラスである StateTriggerBase クラスには、IsActive プロパティと IsActiveChanged イベントがあります。 このイベントは、VisualState が変更されるたびに発生します。 さらに、StateTriggerBase クラスには、オーバーライド可能な OnAttached メソッドと OnDetached メソッドがあります。

重要

バインド可能な StateTrigger.IsActive プロパティによって、継承された StateTriggerBase.IsActive プロパティが隠されます。

次の XAML の例は、StateTrigger オブジェクトを含む Style を示しています。

<Style TargetType="Grid">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="Checked">
                    <VisualState.StateTriggers>
                        <StateTrigger IsActive="{Binding IsToggled}"
                                      IsActiveChanged="OnCheckedStateIsActiveChanged" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="Black" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Unchecked">
                    <VisualState.StateTriggers>
                        <StateTrigger IsActive="{Binding IsToggled, Converter={StaticResource inverseBooleanConverter}}"
                                      IsActiveChanged="OnUncheckedStateIsActiveChanged" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="White" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

この例では、暗黙的な Style によって Grid オブジェクトがターゲットにされています。 バインドされたオブジェクトの IsToggled プロパティが true の場合、Grid の背景色は黒に設定されます。 バインドされたオブジェクトの IsToggled プロパティが false になると、VisualState の変更がトリガーされ、Grid の背景色が白になります。

さらに、VisualState の変更が発生するたびに、VisualStateIsActiveChanged イベントが発生します。 各 VisualState によって、このイベントに対するイベント ハンドラーが登録されます。

void OnCheckedStateIsActiveChanged(object sender, EventArgs e)
{
    StateTriggerBase stateTrigger = sender as StateTriggerBase;
    Console.WriteLine($"Checked state active: {stateTrigger.IsActive}");
}

void OnUncheckedStateIsActiveChanged(object sender, EventArgs e)
{
    StateTriggerBase stateTrigger = sender as StateTriggerBase;
    Console.WriteLine($"Unchecked state active: {stateTrigger.IsActive}");
}

この例では、IsActiveChanged イベントに対するハンドラーが起動すると、ハンドラーは、VisualState がアクティブかどう化を出力します。 たとえば、ビジュアルの状態が Checked から Unchecked に変更されると、次のメッセージがコンソール ウィンドウに出力されます。

Checked state active: False
Unchecked state active: True

Note

カスタム状態のトリガーを作成するには、StateTriggerBase クラスから派生させ、OnAttached メソッドと OnDetached メソッドをオーバーライドして、必要な登録とクリーンアップを実行します。

アダプティブ トリガー

AdaptiveTrigger では、ウィンドウが指定した高さまたは幅になると、VisualState の変更がトリガーされます。 このトリガーには、次の 2 つのバインド可能なプロパティがあります。

Note

AdaptiveTriggerStateTriggerBase クラスから派生しているため、IsActiveChanged イベントに対してイベント ハンドラーをアタッチできます。

次の XAML の例は、AdaptiveTrigger オブジェクトを含む Style を示しています。

<Style TargetType="StackLayout">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="Vertical">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="0" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="Orientation"
                                Value="Vertical" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Horizontal">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="800" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="Orientation"
                                Value="Horizontal" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

この例では、暗黙的な Style によって StackLayout オブジェクトがターゲットにされています。 ウィンドウの幅が、デバイスに依存しない単位で 0 から 800 である場合、Style が適用される StackLayout オブジェクトの向きは垂直方向になります。 ウィンドウの幅が、デバイスに依存しない単位で > = 800 である場合、VisualState の変更がトリガーされ、StackLayout の向きが水平に変わります。

MinWindowHeight および MinWindowWidth プロパティは、個別に使用することも、相互に組み合わせて使用することもできます。 次の XAML では、両方のプロパティを設定する例を示します。

<AdaptiveTrigger MinWindowWidth="800"
                 MinWindowHeight="1200"/>

この例では、AdaptiveTrigger によって、現在のウィンドウの幅がデバイスに依存しない単位で > = 800 であり、かつ現在のウィンドウの高さがデバイスに依存しない単位で > = 1200 である場合に、対応する VisualState が適用されることが示されています。

状態トリガーの比較

CompareStateTrigger では、プロパティが特定の値と等しいときに VisualState の変更がトリガーされます。 このトリガーには、次の 2 つのバインド可能なプロパティがあります。

  • Property (object 型)。トリガーによって比較されているプロパティを示します。
  • Value (object 型)。VisualState が適用される値を示します。

Note

CompareStateTriggerStateTriggerBase クラスから派生しているため、IsActiveChanged イベントに対してイベント ハンドラーをアタッチできます。

次の XAML の例は、CompareStateTrigger オブジェクトを含む Style を示しています。

<Style TargetType="Grid">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="Checked">
                    <VisualState.StateTriggers>
                        <CompareStateTrigger Property="{Binding Source={x:Reference checkBox}, Path=IsChecked}"
                                             Value="True" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="Black" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Unchecked">
                    <VisualState.StateTriggers>
                        <CompareStateTrigger Property="{Binding Source={x:Reference checkBox}, Path=IsChecked}"
                                             Value="False" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="White" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>
...
<Grid>
    <Frame BackgroundColor="White"
           CornerRadius="12"
           Margin="24"
           HorizontalOptions="Center"
           VerticalOptions="Center">
        <StackLayout Orientation="Horizontal">
            <CheckBox x:Name="checkBox"
                      VerticalOptions="Center" />
            <Label Text="Check the CheckBox to modify the Grid background color."
                   VerticalOptions="Center" />
        </StackLayout>
    </Frame>
</Grid>

この例では、暗黙的な Style によって Grid オブジェクトがターゲットにされています。 CheckBoxIsChecked プロパティが false の場合、Grid の背景色は白に設定されます。 CheckBox.IsChecked プロパティが true になると、VisualState の変更がトリガーされ、Grid の背景色が黒になります。

デバイスの状態トリガー

DeviceStateTrigger では、アプリが実行されているデバイスのプラットフォームに基づいて VisualState の変更がトリガーされます。 このトリガーには、1 つのバインド可能なプロパティがあります。

  • Device (string 型)。VisualState が適用されるデバイスのプラットフォームを示します。

Note

DeviceStateTriggerStateTriggerBase クラスから派生しているため、IsActiveChanged イベントに対してイベント ハンドラーをアタッチできます。

次の XAML の例は、DeviceStateTrigger オブジェクトを含む Style を示しています。

<Style x:Key="DeviceStateTriggerPageStyle"
       TargetType="ContentPage">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="iOS">
                    <VisualState.StateTriggers>
                        <DeviceStateTrigger Device="iOS" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="Silver" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Android">
                    <VisualState.StateTriggers>
                        <DeviceStateTrigger Device="Android" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="#2196F3" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

この例では、明示的な Style によって ContentPage オブジェクトがターゲットにされています。 このスタイルを使用する ContentPage オブジェクトでは、その背景色が、iOS ではシルバーに、Android では淡い青に設定されます。

向きの状態トリガー

OrientationStateTrigger では、デバイスの向きが変更されたときに VisualState の変更がトリガーされます。 このトリガーには、1 つのバインド可能なプロパティがあります。

Note

OrientationStateTriggerStateTriggerBase クラスから派生しているため、IsActiveChanged イベントに対してイベント ハンドラーをアタッチできます。

次の XAML の例は、OrientationStateTrigger オブジェクトを含む Style を示しています。

<Style x:Key="OrientationStateTriggerPageStyle"
       TargetType="ContentPage">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="Portrait">
                    <VisualState.StateTriggers>
                        <OrientationStateTrigger Orientation="Portrait" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="Silver" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Landscape">
                    <VisualState.StateTriggers>
                        <OrientationStateTrigger Orientation="Landscape" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Property="BackgroundColor"
                                Value="White" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </Setter>
</Style>

この例では、明示的な Style によって ContentPage オブジェクトがターゲットにされています。 このスタイルを使用する ContentPage オブジェクトでは、縦向きのときはその背景色がシルバーに、横向きのときはその背景色が白に設定されます。