在WPF中创建故事板?

问题描述:

我有很多论文:在WPF中创建故事板?

<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> 

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

有什么建议吗?

如果具有触发器的Grid是所有图像的父级,那么MouseDown事件将从每个图像冒泡到它,因此您只需从trigger中删除SourceName设置。

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

如果我正确理解您的问题,那就是您不希望多次重复相同的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被触发时才会运行。

希望这会有所帮助!