EventTrigger
源代码
EventTrigger.cs这个触发器顾名思义,就是在某个事件被触发时,执行后续的一些动作。它的使用方式与 WPF 原生的 EventTrigger 非常相似,比如都可以指定事件的名称,以及目标对象等。但它与 WPF 原生的 EventTrigger 也有一些不同之处,比如它支持在 Style 中使用,而且执行的动作不局限于操作 Storyboard 等。
WPF 原生的 EventTrigger
首先我们来简单回顾一下 WPF 原生的 EventTrigger 的使用方式。比如我们希望一个按钮在鼠标置于上面时,改变它的背景颜色,我们可以这样做:
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
To="Red" Duration="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
To="Transparent" Duration="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
<Button Content="Click Me" Style="{StaticResource ButtonStyle}">提示
原生的 EventTrigger 只能在 Style.Triggers 中使用,且内部只能是 BeginStoryboard。如果希望瞬间改变背景颜色,通常有这么几种方式:
- 将
Duration设置为0 - 自定义一个
TriggerAction,实现类似Setter的功能(参考) - 改为使用
Trigger,Property="IsMouseOver",Value="True"
行为库的 EventTrigger
接下来我们看一看用行为库的 EventTrigger 如何实现同样的功能:
<Window ...
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<Button Content="Click Me">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:ChangePropertyAction PropertyName="Background" Value="Red" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<i:ChangePropertyAction PropertyName="Background" Value="Transparent" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Window>这样就可以实现效果了。当然,如果同样想操作 Storyboard,只需要修改内部的 Action 即可:
<Window ...
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<Window.Resources>
<Storyboard x:Key="MouseEnterStoryboard">
<!-- ... -->
</Storyboard>
<Storyboard x:Key="MouseLeaveStoryboard">
<!-- ... -->
</Storyboard>
</Window.Resources>
<Button Content="Click Me">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:BeginStoryboardAction Storyboard="{StaticResource MouseEnterStoryboard}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<i:BeginStoryboardAction Storyboard="{StaticResource MouseLeaveStoryboard}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Window>NativeAoT 发布需要注意的地方
对于 WPF 来说,这或许并不是一个问题,毕竟 WPF 目前并不支持 NativeAoT 发布。但对于其他一些框架,比如 Win UI 3、Avalonia UI 来说,这确实是一个合理的需求。然而我们的 EventTrigger 是基于反射来实现的,这就可能会导致 NativeAoT 发布后,相关的功能失效。
但我们也是有对策的。以 Avalonia UI 为例,它的行为库为我们提供了一个 RoutedEventTrigger,它与 EventTrigger 的使用方式基本相同,但它不依赖反射。它的使用方法大致如下:
<Button Name="Click Me">
<Interaction.Behaviors>
<RoutedEventTriggerBehavior RoutedEvent="{x:Static Button.ClickEvent}"
RoutingStrategies="Bubble"
SourceInteractive="ChangeProperty">
<ChangePropertyAction PropertyName="Background" Value="Red" />
</RoutedEventTriggerBehavior>
</Interaction.Behaviors>
</Button>