在窗口中声明时EventTrigger不工作。WPF中的资源

在窗口中声明时EventTrigger不工作。WPF中的资源,wpf,events,triggers,styles,Wpf,Events,Triggers,Styles,我是WPF的新手,所以我可能遗漏了一些重要的东西,但我已经尝试并试图对以下现象做出解释,但没有成功。 基本上,以下代码起作用(显示动画): ... 但是,当我尝试在下面的加载样式中放置eventrigger时,动画停止显示: <Window.Resources> <Storyboard x:Key="LoadStoryBoard" AutoReverse="True" RepeatBehavior="Forever"> <Doub

我是WPF的新手,所以我可能遗漏了一些重要的东西,但我已经尝试并试图对以下现象做出解释,但没有成功。 基本上,以下代码起作用(显示动画):


...
但是,当我尝试在下面的加载样式中放置eventrigger时,动画停止显示:

    <Window.Resources>
    <Storyboard x:Key="LoadStoryBoard"
AutoReverse="True"
RepeatBehavior="Forever">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="button1" 
                Storyboard.TargetProperty="(Button.Opacity)">
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
...
<Style x:Key="Load" TargetType="Button">
...
<Style.Triggers>
    ...
    <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
            </EventTrigger>
</Style.Triggers>
</Style>

...
...
...

在触发器的
样式中
不能使用带有
TargetName
的对象,例如动画。为此,将它们放置在触发器模板
中。引自:

TargetName不适用于样式的触发器集合。样式没有名称范围,因此按名称引用元素是没有意义的。但是模板(DataTemplate或ControlTemplate)有一个名称范围

以下工作:

<Window.Resources>
    <Storyboard x:Key="LoadStoryBoard" AutoReverse="True" RepeatBehavior="Forever">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="button1" Storyboard.TargetProperty="(Button.Opacity)">
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>       

    <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Green" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="FontSize" Value="14" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="SnapsToDevicePixels" Value="True" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border x:Name="button1" CornerRadius="0" Background="{TemplateBinding Background}">
                        <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />                                
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="Orange" />
                        </Trigger>

                        <EventTrigger RoutedEvent="Button.Loaded">
                            <BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <Button Name="TestButton" Style="{StaticResource ButtonStyle}" Width="100" Height="30" Content="Test" Grid.Column="0" Grid.Row="1" />
</Grid>

请注意,现在在
边框中指定的模板中
TargetName


注意:
或者,您可以删除
情节提要。TargetName
,因为它触发的样式不受支持。

您可以正确地认为
事件触发器
不起作用,但这不是因为它是在
参考资料
部分声明的。要看到这一点,您可以将样式直接移动到仍不起作用的
按钮
声明中:

<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>
因此,问题似乎与
参考资料
部分中声明的
情节提要
加载
事件触发时未准备就绪有关。在中也注意到了类似的问题

然而,更让人困惑的是,如果我们随后将
动画
的完整声明放入
参考资料
部分中声明的
样式
,那么现在
样式
起作用了:

<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
控制模板.Triggers
数据模板.Triggers
框架元素.Triggers
(例如
按钮.Triggers

基本上,
FrameworkElement.Triggers
TriggerCollection
中存在一个巨大的缺陷,因为它只接受
EventTrigger
类型的触发器。这可以在MSDN的页面上看到,其中给出了关于此属性可以接受的内容的以下定义:

一个或多个已定义的EventTrigger元素。每一个这样的触发器都是 应包含有效的情节提要动作和引用。注意 此集合只能在页面的根元素上建立

其他触发器属性的MSDN属性页分别声明它们可以接受零个或多个TriggerBase对象,或一个或多个TriggerBase对象

此外,不同的触发器遵循不同的规则——统一的方法肯定会帮助WPF的新手。从页面:

此属性不允许您检查作为存在的触发器 此元素上正在使用的部分样式。它只报告集合 按字面意思添加到集合中的触发器的 标记或代码。元素通常不存在这样的元素 默认情况下(例如通过模板);这是更常见的 来自要在中建立的控件合成的触发器 取而代之的是风格

在行为方面(以及试图确定哪些影响来自于 哪个元素的声明触发器集合),这两个触发器 条件和触发效果可能在此元素上,或者 在逻辑树中的子元素上。请注意,如果您使用 生命周期事件,如加载以获取此集合、子 元素的触发器可能尚未完全加载,集合 将小于运行时的实际值

请注意,仅在元素上建立的触发器集合 支持EventTrigger,而不是属性触发器(Trigger)。如果你需要 属性触发器时,必须将其放置在样式或模板中,然后 然后直接将该样式或模板指定给元素 通过样式属性,或间接通过隐式样式 参考资料

从MSDN的页面:

如果要在数据模板中创建触发器,则 触发器应设置在范围内的属性 数据模板。否则,它可能更适合创建 使用针对包含数据的类型的样式触发。 例如,如果要绑定ListBox控件,则容器是 ListBoxItem对象。如果你
<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>
<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}" />