WPF:在删除动画后防止“已完成”事件被触发

时间:2010-02-24 17:11:53

标签: wpf animation

如何从WPF元素中删除正在运行的动画,使其完成事件不会触发?

提供的解决方案herehere删除动画的可见效果,但完成的事件在动画完成时仍会触发。

这里有一些代码可以演示我的问题(它位于带有Label,Button和TextBox的Window背后的代码中):

    int _count = 0;

    private void button1_Click(object sender, RoutedEventArgs e) {
        myLabel.Content = "Starting animation: " + _count++;

        // Cancel any already-running animations and return
        // the label opacity to 1.0.
        myLabel.BeginAnimation(Label.OpacityProperty, null);
        myLabel.Opacity = 1.0;

        // Create a new animation to fade out the label.
        DoubleAnimation opacityAnim = new DoubleAnimation(1.0, 0.0, TimeSpan.FromSeconds(2), FillBehavior.Stop) {
            BeginTime = TimeSpan.FromSeconds(3)
        };
        opacityAnim.Completed += (sndr, ev) => {
            myTextbox.Text += Environment.NewLine + "Completed fired.";
        };

        // Start the countdown/animation.
        myLabel.BeginAnimation(Label.OpacityProperty, opacityAnim);
    }

如何移除动画以使其不会引发其已完成的事件?

2 个答案:

答案 0 :(得分:3)

取消订阅已完成的事件...这也意味着您必须将已完成的事件处理程序从lambda重写为显式方法:

   DoubleAnimation _opacityAnim; // Created somewhere else.

   private void button1_Click(object sender, RoutedEventArgs e) 
   {
    myLabel.Content = "Starting animation: " + _count++;

    // Cancel any already-running animations and return
    // the label opacity to 1.0.
    _opacityAnim.Completed -= AnimationCompleted;

    myLabel.BeginAnimation(Label.OpacityProperty, null);
    myLabel.Opacity = 1.0;

    // Create a new animation to fade out the label.
    opacityAnim.Completed += AnimationCompleted;

    // Start the countdown/animation.
    myLabel.BeginAnimation(Label.OpacityProperty, opacityAnim);
}

 private void AnimationCompleted(object sender, EventArgs e)
 {
        myTextbox.Text += Environment.NewLine + "Completed fired.";
 }

答案 1 :(得分:0)

我遇到了同样的问题。

在我的项目中,我使用 ProgressBar 为用户提供一段时间,在此期间她/他可以取消命令。用户可以在 ProgressBar 结束之前取消命令,并在 Completed 事件的处理程序中调用实际工作代码。

可以通过调用 myProgressBar.BeginAnimation(ProgressBar.ValueProperty, null) 来移除 ProgressBar 的动画,正如您所提到的。

为了防止被移除动画的 Completed 事件的处理程序被执行,我先检查动画。每次我为 ProgressBar 创建一个 DoubleAnimation 时,我都会将它分配给一个属性。在 Completed 事件的处理程序中,我将首先检查此动画是否与存储在属性中的动画相同。如果没有,那么就返回。并且每次取消动画时,将Property 设置为null。

插图:

DoubleAnimation CurrentAnimation {get; set; }
private void DoSomeWork(){
  DoubleAnimation animation = new(0D, 100D, new(TimeSpan.FromSeconds(3)));
  animation.Completed += (s,e) => {
    lock(lockObj) {
      if(animation != CurrentAnimation)  
        return;
      // do some work here
    }
  CurrentAnimation = animation;
  myProgressBar.BeginAnimation(ProgressBar.ValueProperty, animation);
}
private void CancelIt(){
  lock(lockObj){
    myProgressBar.BeginAnimation(ProgressBar.ValueProperty, null);
    CurrentProperty = null;
  }
}

我认为一定有更好的方法来做到这一点,但现在这将使它按设计运行。