views:

101

answers:

1

This is a two part question from a WPF animation newbie. First, here is my code:

public void AnimatePaneBox(ContentControl destination, 
                           UIElementCollection source)
{
    // Create a NameScope for this page so that
    // Storyboards can be used.
    NameScope.SetNameScope(this, new NameScope());

    Canvas containerCanvas = new Canvas();
    int curInteration = 0;

    foreach (FrameworkElement element in source)
    {
        curInteration++;
        string iterationName = "iter" + curInteration.ToString();

        GeneralTransform tranform;

        try
        {
            // Try to get a transform object.  It may not be possible.
            // (ie if the source or dest is not docked then it 
            // will fail and we cannot animate.)
            tranform = element.TransformToVisual(destination);
        }
        catch (InvalidOperationException e)
        {
            return;
        }


        Point rootPoint = tranform.Transform(new Point(0, 0));

        Rect sourceRelativeRect = new Rect(
              rootPoint.X - (destination.ActualWidth / 2),
              rootPoint.Y - (destination.ActualHeight / 2), 
              element.ActualWidth, element.ActualHeight);

        RectangleGeometry myRectangleGeometry = new RectangleGeometry 
              { Rect = new Rect(0, 0, 0, 0) };

        // Assign the geometry a name so that
        // it can be targeted by a Storyboard.
        RegisterName(iterationName, myRectangleGeometry);              

        Path myPath = new Path
        {
            Fill = ((Canvas)element).Background,
            StrokeThickness = 1,
            Stroke = Brushes.Black,
            Data = myRectangleGeometry
        };


        RectAnimation myRectAnimation = new RectAnimation
        {
            Duration = TimeSpan.FromSeconds(1),
            FillBehavior = FillBehavior.Stop,
            AccelerationRatio = 1,
            // Set the From and To properties of the animation.
            From = sourceRelativeRect,
            To = new Rect(0, 0, 0, 0)
        };

        // Set the animation to target the Rect property
        // of the object named "MyAnimatedRectangleGeometry."
        Storyboard.SetTargetName(myRectAnimation, iterationName);
        Storyboard.SetTargetProperty(myRectAnimation, 
            new PropertyPath(RectangleGeometry.RectProperty));

        // Create a storyboard to apply the animation.
        Storyboard ellipseStoryboard = new Storyboard();
        ellipseStoryboard.Children.Add(myRectAnimation);
        containerCanvas.Children.Add(myPath);

        // Start the storyboard when the Path loads.
        myPath.Loaded += ((sender, e) => ellipseStoryboard.Begin(this));
    }

    containerCanvas.Background = Brushes.Transparent;

    destination.Content = containerCanvas;
}

This takes a list of objects (from a Dotway Zipper Panel) and animates boxes moving from them to a destination.

It works just fine, but to make it work I have to overwrite the destination's content. I can restore it afterwards, but I would rather find a way to make this work without doing that. I have tried to create a EventTrigger and use the BeginStoryboard object, but when I try that I don't see any animation at all.

Also, I would love to know how I could make these animations happen one at a time instead of all at once. (But that is secondary to the main question.)

+1  A: 

Hi Vaccano,

  1. According to the code you've provided, there is no way to animate it without content replacement. But you can always put two controls in the same Grid, for say... They'll occupy the same place. One will be a placeholder for animation container, and another - your actual content you don't want to loose.

  2. Instead of launching them all together in myPath.Loaded += (o, e) => ellipseStoryboard.Begin(this); handler, launch them one by one. firstStoryboard.Completed += (o,e)=> nextStoryboard.Begin(this);

Anvaka