none
Completed event firing when the wrong animation is finished RRS feed

  • Question

  • Hi,

    I got an issue with Animations and the Completed event: I have a window, and 3 animations in XAML. One of them starts when the window is loaded, runs for one minute, then fires the Completed event. In the Completed event handler (in code-behind), I calculate parameters and then restart the animation for one minute.

    The other two animations change the opacity of a Canvas when the mouse enters or exits it.

    I found out that the Completed event gets called also when the "Opacity" animation ends (only sometimes, though), even though no such event was defined. This behaviour is not constant! I found a workaround for the moment, but it's not totally satisfying. I think I am doing something wrong somewhere.

    Code:

      <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
          <EventTrigger.Actions>
            <BeginStoryboard Name="sbdInitBegin" >
              <Storyboard Name="sbdInit">
               <DoubleAnimation
                  Storyboard.TargetName="pnClockCache"
                  Storyboard.TargetProperty="(Canvas.RenderTransform).(RotateTransform.Angle)"
                  From="0"
                  To="{Binding Source={x:Static src:Clock.TimeToDegrees}}"
                  Duration="0:0:5"
                  Completed="Clock_CycleCompleted" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>

        <EventTrigger RoutedEvent="Canvas.MouseEnter">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation
                  Storyboard.TargetName="pnControls"
                  Storyboard.TargetProperty="Opacity"
                  From="0"
                  To="1"
                  Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>

        <EventTrigger RoutedEvent="Canvas.MouseLeave">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation
                  Storyboard.TargetName="pnControls"
                  Storyboard.TargetProperty="Opacity"
                  From="1"
                  To="0"
                  Duration="0:0:1" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
      </Window.Triggers>


    Code behind:

    void Clock_CycleCompleted( object sender, EventArgs e )
    {
      if ( currentStoryboard != null )
      {
        // currentStoryboard is the Storyboard with the current animation
        currentStoryboard.Stop( mainWindow );
        currentStoryboard.Children.Clear();
      }

      RotateTransform transform = ( pnClockCache.RenderTransform as RotateTransform );
      // Register the name in order to be able to use it for SetTargetName
      this.RegisterName( CACHE_TRANSFORM_NAME, transform );

      DoubleAnimation newAnimation = new DoubleAnimation();
      double angleNow = TimeToDegrees;
      newAnimation.From = angleNow;
      newAnimation.To = angleNow + ( 360.0 / 12.0 / 60.0 ); // 360 degrees in 12 hours
      // Next animation over the next minute
      newAnimation.Duration = new Duration( new TimeSpan( 0, 1, 0 ) );
      newAnimation.Completed += new EventHandler( Clock_CycleCompleted );

      Storyboard.SetTargetName( newAnimation, CACHE_TRANSFORM_NAME );
      Storyboard.SetTargetProperty( newAnimation, new PropertyPath( RotateTransform.AngleProperty ) );

      currentStoryboard = new Storyboard();
      // Slow framerate to optimize performance.
      Timeline.SetDesiredFrameRate( currentStoryboard, 1 );
      currentStoryboard.Children.Add( newAnimation );
      currentStoryboard.Begin( mainWindow, true ); // true to make it controllable in code
    }

    Thanks for any idea,
    Laurent
    Thursday, March 15, 2007 2:11 PM