Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Page Transition Control for WPF

0.00/5 (No votes)
19 May 2011 1  
Like the title says... a simple (very simple) page transition control for WPF

About the Control

I have a little side project that I am working on which has multiple pages of information that need to be displayed, and I wanted a slicker way to transition between pages (UserControls) than just popping them into and out of existence (bad for the eyes).

My desire to have better looking transitions led me to develop a very simple control library with several animations built in for more elegant page switches.

The following page transition types are currently included in this version of the control:

  • Fade
  • Slide
  • SlideAndFade
  • Grow
  • GrowAndFade
  • Flip
  • FlipAndFade
  • Spin
  • SpinAndFade

The control itself is very simple... it consists of a UserControl (PageTransition), which contains all of the translation logic. Inside this control, there are several animations in the UserControl.Resources tag, defining all of the available animations. There is also an enum (PageTransitionType) which is mapped as a DependencyProperty that defines which animations are available to the users of the control.

Using the Control

Using the PageTransition control is easy... you just drop the control onto your WPF window, which will look something like this:

<pageTransitions:PageTransition Name="pageTransition" 

Margin="25" TransitionType="SlideAndFade" /> 

Don't forget to add the namespace in your window/control declaration!

At this point, you can make a page change by doing something like this in your code-behind:

NewPage newPage = new NewPage();
pageTransition.ShowPage(newPage);

So, that's about it... pretty simple, right?

Samples

Following are some examples of the animations I am doing in this sample:

<!-- Grow and Fade -->
<Storyboard x:Key="GrowAndFadeIn" >
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleX)" 

    From="0" To="1" Duration="0:0:.75" 

    DecelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleY)" 

    From="0" To="1" Duration="0:0:.75" 

    DecelerationRatio=".9" />
    <DoubleAnimation Duration="0:0:.25" 

    Storyboard.TargetProperty="Opacity" From="0" To="1" />
</Storyboard>

<Storyboard x:Key="GrowAndFadeOut">
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleX)" 

    To="0" Duration="0:0:.75" AccelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleY)" 

    To="0" Duration="0:0:.75" AccelerationRatio=".9" />
    <DoubleAnimation Duration="0:0:.75" 

    Storyboard.TargetProperty="Opacity" To="0" />
</Storyboard>
<!-- Spin -->
<Storyboard x:Key="SpinIn" >
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[2].(RotateTransform.Angle)" 

    From="-360" To="0" Duration="0:0:.75" DecelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleX)" 

    From="0" To="1" Duration="0:0:.75" DecelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleY)" 

    From="0" To="1" Duration="0:0:.75" DecelerationRatio=".9" />            
</Storyboard>

<Storyboard x:Key="SpinOut">
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[2].(RotateTransform.Angle)" 

    To="360" Duration="0:0:.75" AccelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleX)" 

    To="0" Duration="0:0:.75" AccelerationRatio=".9" />
    <DoubleAnimation Storyboard.TargetProperty="(RenderTransform).
    (TransformGroup.Children)[0].(ScaleTransform.ScaleY)" 

    To="0" Duration="0:0:.75" AccelerationRatio=".9" />
</Storyboard>

Here is what I am doing in the code-behind for the actual page transitions themselves. There were some funky issues that I encountered while trying to get the animations working, but everything is resolved now. Notice how I am using the enumeration to determine which animation to load.

/// <summary>
/// Show a new page - this function starts a task to show the page and then returns right away
/// </summary>
public void ShowPage(UserControl newPage)
{            
    pages.Push(newPage);
    Task.Factory.StartNew(() => ShowNewPage());
}

/// <summary>
/// Actual function that unloads the old page (if any) and shows the new page.
/// </summary>
void ShowNewPage()
{
    Dispatcher.Invoke((Action)delegate 
        {
            if (contentPresenter.Content != null)
            {
                UserControl oldPage = contentPresenter.Content as UserControl;

                if (oldPage != null)
                {
                    oldPage.Loaded -= newPage_Loaded;
                    UnloadPage(oldPage);
                }
            }
            else
            {
                ShowNextPage();
            }
                    
        });
}

/// <summary>
/// Pops the next page off of the stack, maps the loaded event, 
/// and then sets the content of the ContentControl to the new page.
/// </summary>
void ShowNextPage()
{
    UserControl newPage = pages.Pop();
    newPage.Loaded += newPage_Loaded;
    contentPresenter.Content = newPage;
}

/// <summary>
/// Starts the animation unloading the existing page - 
/// note the completed event being mapped.
/// </summary>
void UnloadPage(UserControl page)
{
    Storyboard hidePage = (Resources[string.Format("{0}Out", 
    TransitionType.ToString())] as Storyboard).Clone();
    hidePage.Completed += hidePage_Completed;
    hidePage.Begin(contentPresenter);
}

/// <summary>
/// Once the new page is loaded into the ContentControl, the animation is started.
/// </summary>
void newPage_Loaded(object sender, RoutedEventArgs e)
{
    Storyboard showNewPage = Resources[string.Format
    ("{0}In", TransitionType.ToString())] as Storyboard;
    showNewPage.Begin(contentPresenter);
    CurrentPage = sender as UserControl;
}        

/// <summary>
/// Loads the next page after the unload of the previous page
/// </summary>
void hidePage_Completed(object sender, EventArgs e)
{
    contentPresenter.Content = null;
    ShowNextPage();
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here