如何在代码后台停止 XAML 中开始的 WPF 动画和故事板?

8
我创建了一个 XAML 文件中的动画故事板。该故事板在 Button.Click 上开始。但是为了停止动画,我正在尝试在代码后台中停止 storyboard。
代码没有抛出任何异常,但是当我的事件被触发时,动画仍然继续进行。
我认为问题在于 Stop 方法。Stop 需要同一对象来开始和停止动画。但是这里的 storyboard 是在 WPF xaml 中开始的,而我正在代码后台中停止它。
有什么解决办法吗?如何在代码后台获取 Xaml 对象或其他替代方案?
XAML 代码:
<Canvas.Triggers>
            <EventTrigger RoutedEvent="Button.Click" SourceName="ScanButton">
                <EventTrigger.Actions>
                    <BeginStoryboard >
                        <Storyboard  Name="MovingServer" Storyboard.TargetName="ImageMove" RepeatBehavior="Forever" >
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>

后台代码:

    private void EventPublisher_OnScanningFinish(object sender, EventArgs args)
    {
        Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() { this.StopScanningAnimation(); });
    }

    private void StopScanningAnimation()
    {

        ServerView.StoryBoardServerScrolling.Stop(this); //---------- Not Working

        //this.ServerView.Server1Static.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.Server2Static.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.Server3Scrolling.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.SearchingGlass.Visibility = System.Windows.Visibility.Hidden;
    }
3个回答

8

将故事板定义为静态资源,

<MyControl.Resources>
                        <Storyboard Key="MovingServer" Storyboard.TargetName="ImageMove" RepeatBehavior="Forever" >
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
                        </Storyboard>
</MyControl.Resources>

并且从后端代码中引用它,方法如下:

StoryBoard board = (StoryBoard)this.FindResource("MovingServer");
board.stop();

从按钮的“点击”事件开始动画(我不知道你是否在XAML中定义了,但如果你这样做了,以下是如何完成的)。
<Button x:Name="ScanButton" onClick="Scanbutton_Click"></button>


protected void Scanbutton_Click(object Sender, EventArgs e)
{
    StoryBoard board = (StoryBoard)this.FindResource("MovingServer");
    board.start();
}

你测试过这个吗?是指“StaticResources”吗?你是不是只想说“Resources”?那x:Key呢? - H.B.
@H.B. 抱歉,现在无法测试这段代码。你对于StaticResources的理解是正确的,应该是“resources”,我现在会立即更改它。 x:Key;“x:”部分是可选的。 - Timothy Groote
@ 我尝试使用 Windows 资源... 这不起作用... K 更新它 - PawanS
@ Tim,我已经解决了这个问题。实际上,在FindResource上我一直遇到错误,但现在已经解决了。 - PawanS
很高兴听到这个好消息!很抱歉我没能帮上忙,但我很高兴你已经解决了问题! - Timothy Groote
显示剩余2条评论

3
我很感谢Timothy提供的好主意。在这里我将发布我的工作代码。
   /*create this resources as global to that perticular xaml. Need not to be put it in App.xaml
     MyControl could be Window or Page or UserControl */

       <MyControl.Resources>
        <Storyboard x:Key="MovingServer" Storyboard.TargetName="MyImage" RepeatBehavior="Forever" >
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
        </Storyboard>
    </MyControl.Resources>

/* <!-- Now use those animation resources, the place where you want. You can use it as static resource and begin stop animation from code behind OR use it as trigger event --> */

/*    <!-- Static resources--> */
    <Canvas>
        <Image Canvas.Left="0" Canvas.Top="-2" Height="32" Name="MyImage" Width="32" Source="/CCTrayHelper;component/Images/ServerIcon.png" Visibility="Hidden"/>
     <Canvas.Resources>
        <BeginStoryboard x:Key="serverAnimate" Storyboard="{StaticResource MovingServer}" />
     </Canvas.Resources>
    </Canvas>
    <Button x:Name="ScanButton" onClick="Scanbutton_Click" />

/* ****************************************************************** */



  /*  Code behind to start/stop animation*/

//Get the resource value first on current object, so that when you start/stop the animation, it work only on current object
  Storyboard sbImageAnimate = (Storyboard)this.ServerView.FindResource("MovingServer");

//Start the animation on Button Click 
 protected void Scanbutton_Click(object Sender, EventArgs e)
  {   
   this.MyImage.Visibility = System.Windows.Visibility.Visible; 
   sbImageAnimate.Begin();
  } 

 //Stop animation on my own even. You can use it on any event
 private void EventPublisher_OnFinish(object sender, EventArgs args) 
 {   
      Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() { this.StopScanningAnimation(); });  
 }

 private void StopScanningAnimation()  
   {
   sbImageAnimate.Stop();
   this.MyImage.Visibility = System.Windows.Visibility.Hidden; 
   } 

3
我使用Storyboard类的Stop()方法来解决问题,具体如下:
myStoryBoard.Stop(this.LayoutRoot);

使用这个解决方案,您不需要在资源中声明Storyboard。

2
为了做到这一点,当你启动动画时,必须将第二个参数设置为true:Begin(DependencyObject ...,allowsModification)。 - Sonhja

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接