Triggers

浏览示例。 浏览示例

.NET 多平台应用 UI (.NET MAUI) 触发器允许在 XAML 中以声明方式表达动作,以基于事件或数据更改来修改控件的外观。 此外,状态触发器是一种专门的触发器组,用于定义何时应应用 VisualState

可以将触发器直接分配给控件的 Triggers 集合,或将其添加到要应用于多个控件的页面级或应用级资源字典。

属性触发器

表示 Trigger 是一种触发器,在指定属性满足指定条件时应用属性值或执行操作。

以下示例展示了一个Trigger,当它聚焦时会改变Entry的背景色:

<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

使用样式应用触发器

还可以将触发器添加到 Style 控件、页面或应用程序声明中 ResourceDictionary。 以下示例声明页面上所有控件的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 为空时,DataTrigger 禁用 Button 的情况:

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

在此示例中,当长度 Entry 为零时,将激活触发器。

小窍门

评估 Path=Text.Length 时始终为目标属性(例如) Text=""提供默认值,因为否则它将是 null ,并且触发器不会像预期那样工作。

此外,还可以指定可选 EnterActions 集合和 ExitActions 集合。 有关详细信息,请参阅 EnterActions 和 ExitActions

事件触发器

EventTrigger 代表一个触发器,该触发器应用一组操作以响应某个事件。 与 Trigger 不同,EventTrigger 没有终止状态的概念,因为一旦引发事件的条件不再成立,操作将不会被撤销。

EventTrigger只需要设置一个属性Event

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

在此示例中,没有 Setter 元素。 而是有一个 NumericalValidationTriggerAction 对象。

注释

事件触发器不支持 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要小心。 一个实例将在控件之间共享,因此配置一次的任何状态都将应用于所有实例。

多重触发器

满足一组条件时,MultiTrigger 表示应用属性值或执行动作的触发器。 所有条件都必须为 true 之后才能应用 Setter 对象。

以下示例演示一个MultiTrigger绑定到两个Entry对象:

<Entry x:Name="email"
       Text="" />
<Entry x:Name="phone"
       Text="" />
<Button Text="Save">
    <Button.Triggers>
        <MultiTrigger TargetType="Button">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding x:DataType='Entry',
                                                    Source={x:Reference email},
                                                    Path=Text.Length}"
                                  Value="0" />
                <BindingCondition Binding="{Binding x:DataType='Entry',
                                                    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集合定义了在满足触发条件时将被调用的集合。 当不再满足触发条件时,类型ExitActionsIList<TriggerAction>集合定义了将要调用的集合。

注释

EventTrigger类会忽略定义在EnterActionsExitActions集合中的TriggerAction对象。

以下示例显示了一个属性触发器,该触发器指定了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);
    }
}

注释

你可以在触发器中提供EnterActionsExitActions以及Setter的对象,但请注意,Setter的对象会立即调用(它们不会等待EnterActionExitAction完成)。

状态触发器

状态触发器是一组专用的触发器,用于定义 VisualState 应用条件。

状态触发器已添加到 VisualStateStateTriggers 集合中。 此集合可以包含单个状态触发器或多个状态触发器。 当集合中的任何状态触发器处于活动状态时,将应用 A VisualState

使用状态触发器控制视觉状态时,.NET MAUI 使用以下优先规则来确定将处于活动状态的触发器(和相应的 VisualState)。

  1. 派生自 StateTriggerBase. 的任何触发器。
  2. 由于MinWindowWidth条件被满足,AdaptiveTrigger已被激活。
  3. 由于MinWindowHeight条件得到满足,AdaptiveTrigger已被激活。

如果多个触发器同时处于活动状态(例如两个自定义触发器),则标记中声明的第一个触发器优先。

注释

可以在元素 Style中或直接在元素中设置状态触发器。

有关视觉状态的详细信息,请参阅 视觉状态

状态触发器

StateTrigger 类派生自 StateTriggerBase 类,并具有 IsActive 可绑定属性。 属性IsActive更改值时,会触发StateTriggerVisualState更改。

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

注释

可以通过从 StateTriggerBase 类派生并重写 OnAttachedOnDetached 方法来创建自定义状态触发器,以执行任何必需的注册和清理。

自适应触发器

某个AdaptiveTrigger会触发VisualState更改,当窗口达到指定的高度或宽度时。 此触发器有两个可绑定属性:

注释

AdaptiveTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 IsActiveChanged

以下 XAML 示例显示了一个Style,其中包含AdaptiveTrigger对象。

<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 个与设备无关的单位之间时, StackLayout 应用窗口的对象 Style 将具有垂直方向。 当窗口宽度 >为 = 800 个与设备无关的单位时, VisualState 将触发更改,并将 StackLayout 方向更改为水平。

MinWindowHeightMinWindowWidth属性可以独立使用,也可以彼此结合使用。 以下 XAML 演示了设置这两个属性的示例:

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

在此示例中,AdaptiveTrigger 表示当当前窗口宽度为 VisualState = 800 与设备无关的单位,并且当前窗口高度为 > = 1200 与设备无关的单位时,将应用相应的 >。

注释

有关与设备无关的单元的详细信息,请参阅 与设备无关的单元

比较状态触发器

CompareStateTrigger当属性等于特定值时,触发VisualState更改。 此触发器有两个可绑定属性:

  • Property,类型 object,指示触发器正在比较的属性。
  • Value,类型 object,指示应应用 VisualState 的值。

注释

CompareStateTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 IsActiveChanged

以下 XAML 示例显示了一个Style,其中包含CompareStateTrigger对象。

<Style TargetType="Grid">
    <Setter Property="VisualStateManager.VisualStateGroups">
        <VisualStateGroupList>
            <VisualStateGroup>
                <VisualState x:Name="Checked">
                    <VisualState.StateTriggers>
                        <CompareStateTrigger Property="{Binding x:DataType='CheckBox', 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 x:DataType='CheckBox', 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>
    <Border BackgroundColor="White"
            StrokeShape="RoundRectangle 12"
            Margin="24"
            Padding="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>
    </Border>
</Grid>

在此示例中,隐式 Style 针对 Grid 对象。 当IsCheckedCheckBox的属性是false时,Grid的背景色设置为白色。 当CheckBox.IsChecked属性变为true时,会触发VisualState更改,并且Grid的背景色变为黑色。

设备状态触发器

根据设备平台,应用的 DeviceStateTrigger 触发 VisualState 更改。 此触发器具有单个可绑定属性:

  • Device,类型为 string,用于指示应在哪个平台上应用 VisualState 的设备。

注释

DeviceStateTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 IsActiveChanged

以下 XAML 示例显示了一个Style,其中包含DeviceStateTrigger对象。

<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更改。 此触发器具有单个可绑定属性:

注释

OrientationStateTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 IsActiveChanged

以下 XAML 示例显示了一个Style,其中包含OrientationStateTrigger对象。

<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 使用样式的对象在竖屏模式时背景色设为银色,在横屏模式时背景色设为白色。