触发器
.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。
使用样式应用触发器
还可将触发器添加到控件、页面或应用程序 ResourceDictionary 中的 Style 声明。 以下示例声明页面上所有 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 的长度为零时将激活触发器。
提示
评估 Path=Text.Length
时,始终为目标属性(例如 Text=""
)提供默认值,因为若非如此,它将为 null
,并且触发器不会像预期那样工作。
此外,可以指定可选的 EnterActions 和 ExitActions 集合。 有关详细信息,请参阅 EnterActions 和 ExitActions。
事件触发器
EventTrigger 表示应用一组操作以响应一个事件的触发器。 与 Trigger 不同,EventTrigger 没有状态终止的概念,因此若不再符合引发事件的条件,相应操作也不会撤消。
EventTrigger 只需要设置 Event
属性:
<EventTrigger Event="TextChanged">
<local:NumericValidationTriggerAction />
</EventTrigger>
在此示例中,不存在 Setter 元素。 而是存在一个 NumericalValidationTriggerAction
对象。
注意
事件触发器不支持 EnterActions 和 ExitActions。
触发器操作实现必须:
- 实现泛型 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 表示一个触发器,它会在一组条件得到满足时应用属性值或执行操作。 应用 Setter 对象前,必须满足所有条件。
以下示例演示绑定到两个 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
通过指定 EnterActions 和 ExitActions 集合,并创建 TriggerAction<T> 实现,是触发发生时实现更改的替代方法。
类型为 IList<TriggerAction>
的 EnterActions 集合用于定义在满足触发条件时将调用的集合。 类型为 IList<TriggerAction>
的 ExitActions 集合用于定义在不再满足触发条件后将调用的集合。
注意
EventTrigger 类将忽略 EnterActions 和 ExitActions 集合中定义的 TriggerAction 对象。
以下示例展示了指定 EnterAction
和 ExitAction
的属性触发器:
<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);
}
}
注意
可以在触发器中同时提供 EnterActions、ExitActions 和 Setter 对象,但注意,Setter 对象将立即调用(不会等待 EnterAction
或 ExitAction
完成)。
状态触发器
状态触发器是一组专门的触发器,它们定义了在哪些条件下应该应用 VisualState。
状态触发器添加到 VisualState 的 StateTriggers 集合。 此集合可以包含一个或多个状态触发器。 当此集合中的任何状态触发器处于活动状态时,便会应用 VisualState。
使用状态触发器来控制视觉状态时,.NET MAUI 使用以下优先规则来确定哪个触发器(以及相应的 VisualState)将处于活动状态:
- 任何派生自 StateTriggerBase 的触发器。
- 因满足 MinWindowWidth 条件而激活的 AdaptiveTrigger。
- 因满足 MinWindowHeight 条件而激活的 AdaptiveTrigger。
如果多个触发器同时处于活动状态(例如,两个自定义触发器),则标记中声明的第一个触发器优先。
注意
状态触发器可以在 Style 中设置,也可以直接对元素设置。
有关视觉状态的详细信息,请参阅视觉状态。
状态触发器
StateTrigger 类派生自 StateTriggerBase 类,包含 IsActive 可绑定属性。 当 IsActive 属性值更改时,StateTrigger 触发 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 发生更改,就会引发 VisualState 的 IsActiveChanged 事件。 每个 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 类派生,并重写 OnAttached
和 OnDetached
方法来执行任何所需注册和清理。
自适应触发器
当窗口为指定高度或宽度时,AdaptiveTrigger 触发 VisualState 更改。 此触发器有以下两个可绑定属性:
- 类型为
double
的 MinWindowHeight,指明触发应用 VisualState 的最小窗口高度。 - 类型为
double
的 MinWindowWidth,指明触发应用 VisualState 的最小窗口宽度。
注意
由于 AdaptiveTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 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 更改。 此触发器有以下两个可绑定属性:
- 类型为
object
的 Property,指明触发器所比较的属性。 - 类型为
object
的 Value,指明触发应用 VisualState 的值。
注意
由于 CompareStateTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 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 对象为目标。 当 CheckBox 的 IsChecked
属性为 false
时,Grid 的背景色设置为白色。 当 CheckBox.IsChecked
属性变为 true
时,将触发 VisualState 更改,并且 Grid 的背景色变为黑色。
设备状态触发器
DeviceStateTrigger 根据应用运行所在的设备平台触发 VisualState 更改。 此触发器有以下一个可绑定属性:
- 类型为
string
的 Device,指明触发应用 VisualState 的设备平台。
注意
由于 DeviceStateTrigger 派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 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 更改。 此触发器有以下一个可绑定属性:
- 类型为 DisplayOrientation 的 Orientation,指明触发应用 VisualState 的方向。
注意
由于 OrientationStateTrigger
派生自 StateTriggerBase 类,因此可以将事件处理程序附加到 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 对象使用的 style 在方向为垂直时将背景色设置为银色,在方向为水平时将背景色设置为白色。