您是正确的,EventTrigger
它不起作用,但这不是因为它是在该Resources
部分中声明的。要看到这一点,您可以将您的样式直接移动到Button
它仍然不起作用的声明中:
<Button x:Name="button1" Grid.Column="0" Grid.Row="1">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
但是,如果我们Animation
从该Resources
部分移动声明,它会再次起作用:
<Button x:Name="button1" Grid.Column="0" Grid.Row="1">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Button.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
因此,问题似乎与事件触发时Storyboard
该部分中的声明Resources
尚未准备好有关。这篇文章Loaded
中提到了一个类似的问题。
但是,只是为了让事情更加混乱,如果我们然后将完整的声明Animation
放入Style
该部分的声明中Resources
,那么现在的Style
作品:
<Window.Resources>
<Style x:Key="Load" TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Button.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Button x:Name="button1" Grid.Column="0" Grid.Row="1" Style="{StaticResource Load}" />
我可以推测为什么会发生这种情况,但我猜很少有 WPF 开发人员真正知道为什么一切都是这样的......我了解到,如果特定的声明方法有效,请使用它并如果没有,请尝试不同的。
背景
在 WPF 中,我们可以定义四个地方Triggers
;Style.Triggers
, ControlTemplate.Triggers
,DataTemplate.Triggers
和FrameworkElement.Triggers
(例如Button.Triggers
)。
基本上,它有一个巨大的缺陷FrameworkElement.Triggers
TriggerCollection
,它只接受 type 的触发器EventTrigger
。这可以在 MSDN 的FrameworkElement.Triggers 属性页面上看到,其中对该属性可以接受的内容给出了以下定义:
一个或多个已定义的 EventTrigger 元素。每个此类触发器都应包含有效的故事板操作和引用。请注意,此集合只能在页面的根元素上建立。
其他触发器属性的 MSDN 属性页分别声明它们可以接受零个或多个 TriggerBase 对象,或者一个或多个 TriggerBase 对象。
此外,不同的触发器遵循不同的规则——统一的方法肯定会帮助 WPF 的新手。从FrameworkElement.Triggers 属性页面:
此属性不允许您检查作为在此元素上使用的样式的一部分而存在的触发器。它仅报告以标记或代码形式添加到集合中的触发器集合。默认情况下,元素通常不存在此类元素(例如通过模板);更常见的是,来自控制合成的触发器改为在样式中建立。
在行为方面(并试图确定哪个效果来自哪个元素声明的 Triggers 集合),触发条件和触发效果都可能在此元素上,也可能在逻辑树中的子元素上。请注意,如果您使用诸如 Loaded 之类的生命周期事件来获取此集合,则子元素的触发器可能尚未完全加载,并且集合将小于运行时的实际值。
注意,在一个元素上建立的触发器集合只支持EventTrigger,不支持属性触发器(Trigger)。如果您需要属性触发器,则必须将它们放在样式或模板中,然后直接通过 Style 属性或间接通过隐式样式引用将该样式或模板分配给元素。
从MSDN的DataTemplate.Triggers 属性页面:
如果您在数据模板中创建触发器,则触发器的设置者应该设置数据模板范围内的属性。否则,使用以包含数据的类型为目标的样式创建触发器可能更合适。例如,如果要绑定 ListBox 控件,则容器是 ListBoxItem 对象。如果您使用触发器来设置不在 DataTemplate 范围内的属性,那么创建 ListBoxItem 样式并在该样式中创建触发器可能更合适。
不幸的是,所有这些额外的信息实际上并不能回答您关于为什么动画资源在资源中不起作用的问题Style
,但希望现在,您可以看到整个Trigger
区域有点复杂、混乱。我自己不是专家,我只是倾向于使用任何有效的声明Trigger
s 的方法。
我希望这在某种程度上有所帮助。