在WPF中启动故事板?

时间:2011-11-30 19:17:46

标签: wpf animation

我有很多论文:

<Image x:Name="Foo" Grid.Column="0" Grid.Row="0" Source="1.png" Style="{StaticResource imageStyle}" 
                       ToolTipService.InitialShowDelay="0" ToolTipService.ShowDuration="360000" ToolTipService.BetweenShowDelay="10000" ToolTip="fffffff"/>

<Image x:Name="Foo2" Grid.Column="1" Grid.Row="0" Source="2.png" Style="{StaticResource imageStyle}" 
                       ToolTipService.InitialShowDelay="0" ToolTipService.ShowDuration="360000" ToolTipService.BetweenShowDelay="10000" ToolTip="eeeeeeeee"/>

<Image x:Name="Foo3" Grid.Column="2" Grid.Row="0" Source="3.png" Style="{StaticResource imageStyle}" 
                       ToolTipService.InitialShowDelay="0" ToolTipService.ShowDuration="360000" ToolTipService.BetweenShowDelay="10000" ToolTip="ddddddddddddd"/>

现在我的动画故事板只有在有人点击Foo图片时才会触发。

<Grid.Triggers>
    <EventTrigger RoutedEvent="Image.MouseDown" SourceName="Foo">
        <BeginStoryboard Name="mySlider">
            <Storyboard>
                <ThicknessAnimation Storyboard.TargetName="contentHolder"
                                    Storyboard.TargetProperty="Margin"
                                    Duration="0:0:1" From="0 0 0 0" To="-800 0 0 0" />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Grid.Triggers>

如果有人点击上面三张图片中的任何一张图片,我该如何制作动画?他们共同的共同点是风格,所以也许有一些方法可以使用它?

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,那就是您不希望多次重复相同的EventTrigger次,每次来源一次。如果您遗漏SourceName,那么即使不是来自您的某个图片,您的动画也会针对任何未处理的MouseDown路由事件启动(因为MouseDown是一个非常通用的冒泡路由事件)

一个解决方案是拥有一个自定义Image类(可能称为MyImage),它将检测MouseDown事件何时发生,并作为响应触发一个非常自定义的RoutedEvent (说MyImageRoutedEvent)。然后,您EventTrigger可以收听MyImageRoutedEvent,因为只有MyImage可以触发此事件。因此,仅当MouseDown事件来自您的MyImage个实例之一时,才会运行动画。

或者,您可以通过附加行为实现此行为。我们的想法是将行为配置为拦截指定的事件(通过附加属性),并且当从参与该行为的元素触发该事件时,该事件被标记为已处理并且将触发新的自定义事件。然后,您的EventTrigger会收听新的自定义事件。

示例XAML:

<StackPanel>

    <StackPanel.Resources>

        <Style x:Key="rectangleStyle" TargetType="{x:Type Rectangle}">
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="100" />
            <Setter Property="l:EventInterceptBehaviour.OriginalRoutedEvent" Value="UIElement.MouseDown" />
        </Style>

        <Style TargetType="{x:Type ContentControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ContentControl}">
                        <StackPanel>
                            <Rectangle Style="{StaticResource rectangleStyle}" Fill="Red" />
                            <Rectangle Style="{StaticResource rectangleStyle}" Fill="Green" />
                            <Rectangle Style="{StaticResource rectangleStyle}" Fill="Blue" />
                            <Border BorderBrush="Black" x:Name="contentBorder">
                                <ContentPresenter HorizontalAlignment="Center"/>
                            </Border>
                        </StackPanel>
                        <ControlTemplate.Triggers>
                            <EventTrigger RoutedEvent="l:EventInterceptBehaviour.InterceptedEvent">
                                <BeginStoryboard Name="mySlider">
                                    <Storyboard>
                                        <ThicknessAnimation Storyboard.TargetName="contentBorder"
                                                            Storyboard.TargetProperty="BorderThickness"
                                                            Duration="0:0:1" To="10" FillBehavior="Stop" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </StackPanel.Resources>

    <ContentControl Content="Content Placeholder" />

</StackPanel>

示例行为:

public static class EventInterceptBehaviour
{
    #region InterceptedEvent Attached Routed Event

    public static readonly RoutedEvent InterceptedEventEvent = EventManager.RegisterRoutedEvent("InterceptedEvent",
                                                                                  RoutingStrategy.Bubble,
                                                                                  typeof(RoutedEventHandler),
                                                                                  typeof(EventInterceptBehaviour));

    public static void AddInterceptedEventHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is FrameworkElement)
        {
            var element = (FrameworkElement)d;
            element.AddHandler(InterceptedEventEvent, handler);
        }
    }

    public static void RemoveInterceptedEventHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is FrameworkElement)
        {
            var element = (FrameworkElement)d;
            element.RemoveHandler(InterceptedEventEvent, handler);
        }
    }

    #endregion

    #region OriginalRoutedEvent Attached Dependency Property

    public static void SetOriginalRoutedEvent(FrameworkElement element, RoutedEvent value)
    {
        element.SetValue(OriginalRoutedEventProperty, value);
    }

    public static RoutedEvent GetOriginalRoutedEvent(FrameworkElement element)
    {
        return (RoutedEvent)element.GetValue(OriginalRoutedEventProperty);
    }

    public static readonly DependencyProperty OriginalRoutedEventProperty =
        DependencyProperty.RegisterAttached("OriginalRoutedEvent", typeof(RoutedEvent),
                                            typeof(EventInterceptBehaviour),
                                            new FrameworkPropertyMetadata(OnOriginalRoutedEventPropertyChanged));

    #endregion

    private static void OnOriginalRoutedEvent(object sender, RoutedEventArgs e)
    {
        var element = (FrameworkElement)sender;
        element.RaiseEvent(new RoutedEventArgs(InterceptedEventEvent, element));
        e.Handled = true;
    }

    private static void OnOriginalRoutedEventPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement)
        {
            var element = (FrameworkElement)d;
            element.AddHandler((RoutedEvent)e.NewValue, new RoutedEventHandler(OnOriginalRoutedEvent));
        }
    }
}

在此示例中,样式应用于每个Rectangle,并且附加行为配置为拦截MouseDown路由事件,并将此事件替换为InterceptedEvent。然后,只有在InterceptedEvent被触发时才会运行动画。

希望这有帮助!

答案 1 :(得分:1)

如果带有触发器的Grid是所有图片的父级,则MouseDown事件无论如何都会从每个图片冒泡到它,所以您只需删除{{1}从触发器设置。

否则,您可以将SourceName设置为Image的父级。