Navigation with Animated Transition Effects

One of the common things that developers want to do is to navigate between pages of their application. Once they have that, then they want to make the transitions look pretty. The attached project (see below) show how to do use a TransitionControl to do both. The TransitionControl is extensible, so you can even write your own transitions. You can download the project by clicking on the Attachment links on the bottom of the post. Here is a snapshot of the demo app that shows the Image Page in mid-spin as it appears on top of the Controls Page:

How it works

The TransitionControl is subclassed from UserControl. This is its public API:

public partial class TransitionControl : UserControl

{

    public TransitionControl();

    public void GoTo(FrameworkElement newContent, ITransition transition, TimeSpan duration);

    public void Completed();

    public void CurrentToBack();

    public void CurrentToFront();

    public FrameworkElement New { get; }

    public FrameworkElement Current { get; }

}

 

The GoTo method is the only method that you'll call to display new content. You pass in the new content, the transition that you wish to use, and how long you want the transition to take. The other methods and properties are for use by the transition. The sample application uses a TransitionControl for its main, but not the entire page. There is nothing magic about it; it is just a control. You can use more than one, make them any size you like, fill up the page with it, etc.

ITransition

The ITransition interface is as follows:

public interface ITransition

{

void GoTo(TransitionControl control, TimeSpan duration);

void Stop();

}

The Goto method is called by the TransitionControl, which passes in itself and the duration it received in its GoTo method. The Stop method is called by the TransitionControl when the TransitionControl.GoTo method is called before the a transition already in progress can finish.

The simplest implementation of ITransition included in the project is Swap:

/// <summary>

/// This is the simplest transition class, and is about all you can really do

/// without animating. This is a synchronous transition.

/// </summary>

public class Swap : ITransition

{

public void GoTo(TransitionControl control, TimeSpan duration)

{

control.CurrentToBack();

control.Completed();

}

public void Stop()

{

// Nothing to do here, since this is not async

}

}

The Swap transition ignores the duration and simply bring the new content to the front by calling control.CurrentToBack() and lets the control know that the transition is finished by calling control.Completed.

Animated transitions

Of course, merely swapping the content is not all that interesting. To get some nice effects, we'll need to animate. There is an abstract class in the sample that helps with this.

/// <summary>

/// The StoryboardTransition classs is designed to encapsulate an asynchronous,

/// animated transition.

/// </summary>

public abstract class StoryboardTransition : ITransition

{

public void GoTo(TransitionControl control, TimeSpan duration)

{

_control = control;

_storyboard = new Storyboard() { Duration = duration };

Storyboard.Completed += storyboardCompleted;

control.New.Resources.Add("storyboard", _storyboard);

GoToCore(duration);

Storyboard.Begin();

}

public void Stop()

{

_storyboard.Stop();

}

protected Storyboard Storyboard { get { return _storyboard; } }

protected TransitionControl Control { get { return _control; } }

// The subclass adds their animations to the Storyboard in this override.

protected abstract void GoToCore(TimeSpan duration);

protected void storyboardCompleted(object sender, EventArgs e)

{

CompletedCore();

_control.Completed();

}

// The subclass can remove the stuff needed only for the transition,

// such as clips or transforms.

protected virtual void CompletedCore() {}

private Storyboard _storyboard;

private TransitionControl _control;

}

To implement a subclass of the StoryboardTransition, you'll need to override GoToCore and add your animations to the Storyboard provided. You may also need to add some things to the new content, such as RenderTransforms or Clips. By overriding the CompletedCore transition, you get the opportunity to remove whatever you added that is no longer needed.

The FadeIn transition

The FadeIn transition is a simple animated transition that gives you an idea of how to subclass StoryboardTransition:

public class FadeIn : StoryboardTransition

{

protected override void GoToCore(TimeSpan duration)

{

Control.CurrentToBack();

DoubleAnimation opacityAnimation = new DoubleAnimation() { From = 0, To = 1, Duration = duration, FillBehavior=FillBehavior.HoldEnd };

Storyboard.SetTarget(opacityAnimation, Control.New);

Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity"));

Storyboard.Children.Add(opacityAnimation);

}

}

The GoToCore method is overridden (as it must be, since it abstract). The first thing it does is send the current content to the back, since the new content will be appearing in front of it. They it sets up the opacity animation and adds it to the Storyboard. That's all there is to do, because there is nothing to clean up. Note that the FillBehavior has been set to HoldEnd, meaning that if the animation is stopped, it will jump to the To value and stay there.

Other transitions

Here are the transitions that the project supplies:

Swap
Wipe (you can specify the direction)
FadeIn
FadeOut
(I thought there would be a difference between fading in and out, but now I'm not so sure...)
Open (a circle opens up to reveal the new content)
Close (a circle closes, hiding the old content)
Grow (the new content zooms in from a point in the middle of the screen; spinning is optional)
Shrink (the old content disppears to a point in the middle of the screen; spinning is optional)

You can also write your own. If you make a cool transition, I'd love to see it.

TransitionApp.zip