Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Simplify Page Transitions in Windows Phone 7 Silverlight Applications

Download

Right click “Save as…”

  • WMV (WMV Video)
  • MP3 (Audio only)
  • MP4 (iPhone, Android)
  • WMV (WMV Video)

Update: To see how to extend this solution for custom per-page transitions, see my follow-on article.

If you have played around with Silverlight on Windows Phone 7, one thing you may have tried to figure out is how to add nice transitions between different pages of your application. By default, Windows Phone page transitions aren’t really transitions at all. The new PhoneNavigationPage is just popped into the root PhoneNavigationFrame. Effective, yes. Cool? Certainly not. Face it, modern mobile applications need to not only be functional, but also stylish. Simple “snap” transitions just don’t cut it.

The most common solution to this problem is to use brute force and manage the transitions yourself. You commonly see a “pattern” used in WP7 apps where events in your current page launch a Storyboard animation. When that animation is complete, the actual navigation to the new page is invoked and the new page then runs its own Storyboard once it is loaded. It looks something like this…

// CURRENT PAGE private void CurrentPage_Click(object sender, EventArgs e) 
{
    SomeStoryboard.Completed += new EventHandler(SomeStoryboard_Completed);     
    SomeStoryboard.Begin();
}






void SomeStoryboard_Completed(object sender, EventArgs e)
{
    NavigationService.Navigate(new Uri("/Favorites", UriKind.Relative));
}

 

// NEWPAGE 
protected override void OnNavigatedTo(Microsoft.Phone.Navigation.PhoneNavigationEventArgs e)
{
    base.OnNavigatedTo(e);  
   SomeNewStoryboard.Begin();
}

It’s a straightforward solution, and it works just fine if your app has only a few pages. If you have lots of pages in your application, however, it becomes quite tedious and hard to maintain.

A better solution can be found by turning to the Silverlight Toolkit. The great thing about having Silverlight on WP7 is that you can leverage many existing Silverlight assets. In this case, we leverage the TransitioningContentControl from the Toolkit. The TransitioningContentControl was created for the traditional navigation-based Silverlight application to solve the same problem we are currently facing.

To get started, download the Silverlight Toolkit from CodePlex. Once installed, you will need to add the System.Windows.Controls.Layout.Toolkit assembly to your WP7 project.

If you are not familiar with the TransitioningContentControl, it's a fairly simple control. The TCC is comprised of two ContentPresenters – current and previous. When you update the Content property of the TCC, it will take the content of the CurrentContentPresenter (if present) and move it to the PreviousContentPresenter. The new content is loaded into the CurrentContentPresenter. The TCC, however, manages the visibility of the previous and current ContentPresenters so that the “old” content is visible and the “new” content is hidden. It then uses a Storyboard, which is defined as part of the TCC’s VisualStateManager, to transition from the “old” content to the “new” content. If you are not familiar with Storyboards, the Visual State Manager, or other designer-type topics, have no fear. The TCC comes with a set of standard transitions, which you can use out of the box.

Getting the TCC to work with our WP7 app is a simple process. First, we need to modify the ControlTemplate for our PhoneNavigationFrame to use the TCC. By doing so, we automatically enable transitions between any PhoneNavigationPages we add to our app. To change the PhoneNavigationFrame, open the App.xaml file. Then, add a couple of namespaces to the xaml:

xmlns:layout="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"

Now, modify the PhoneNavigationFrame as shown below:

<phoneNavigation:PhoneApplicationFrame x:Name="RootFrame" Source="/MainPage.xaml">     
    <phoneNavigation:PhoneApplicationFrame.Template>
        <ControlTemplate>     
            <layout:TransitioningContentControl Content="{TemplateBinding Content}" Style="{StaticResource TransitioningStyle}"/>
        </ControlTemplate>
    </phoneNavigation:PhoneApplicationFrame.Template> </phoneNavigation:PhoneApplicationFrame>

The TCC has its Style property set to a StaticResource. This Style provides the default transitions and is also where you would add your own VisualStates and Storyboards if you would like to add custom transitions.  This Style can be found in the Silverlight Toolkit in the TCC Sample Application, or you can get it from the sample WP7 application linked to at the end this article. The Style is long, so I won’t show the entire thing here, but the first parts of the Style are included below to give you an idea of what the Style contains and how it is used by the TCC.

<Style x:Key="TransitioningStyle" TargetType="layout:TransitioningContentControl"> 
    <Setter Property="Transition" Value="DefaultTransition" />
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="layout:TransitioningContentControl">
            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
            <vsm:VisualStateManager.VisualStateGroups>
            <vsm:VisualStateGroup x:Name="PresentationStates">
                <vsm:VisualState x:Name="DefaultTransition">
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CurrentContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                        <SplineDoubleKeyFrame KeyTime="00:00:02.300" Value="1" />
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                        <SplineDoubleKeyFrame KeyTime="00:00:02.300" Value="0" />
                        </DoubleAnimationUsingKeyFrames>
                     </Storyboard>
                </vsm:VisualState>
                <vsm:VisualState x:Name="Normal">
                    <Storyboard>
                    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>
                                Collapsed
                            </Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </vsm:VisualState>


Though I won’t break the Style down in detail, I’ll point a couple of highlights. First, the Transition property is set to the VisualState that you would like to use as the transition between pages. Every transition will use this VisualState storyboard. The DefaultTransition VisualState is an example of how Storyboards are constructed for use in a transition. As you can see, each Storyboard must target both the CurrentContentPresentationSite and the PreviousContentPresentationSite (these are the ContentPresenters discussed earlier). You can target more than one property, if you like. Below is a custom transition that rotates the projection plane and the opacity of the ContentPresenters.

<vsm:VisualState x:Name="SwingTransition">
    <Storyboard>         
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="PreviousContentPresentationSite">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="90"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PreviousContentPresentationSite">
            <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" Storyboard.TargetName="PreviousContentPresentationSite" />
        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" Storyboard.TargetName="CurrentContentPresentationSite" />
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="CurrentContentPresentationSite">
            <EasingDoubleKeyFrame KeyTime="0" Value="90"/> <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="CurrentContentPresentationSite">
            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>         
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</vsm:VisualState>

That’s it. You now have transitions any time you Navigate to a new PhoneNavigationPage

Tag:

Follow the Discussion

  • Thanks, I like the video. Would love to see a bit more high quality video. I downloaded the HWMV (High) but can't read the blend screens.

  • Sources please?

  • I will be getting source up to my site, slickthought.net, in the coming days.  I had a bit of a hoster issue that took my site offline so we had to pull the download links from the article.  Check the site at the end of the week and I should have a post up pointing to the download.

  • HikariHikari Hikari

    Great example! That's what I needed.

     

     

    OOOPS, SOME PROBLEM

    For the reasons I don't know, adding a reference to Layout.Toolkit prevents aplication from starting, i.e. I see only black screen instead of first page. This happens even when running your source file.

     

    I have Windows Phone 7 CTP from April refresh and Silverlight Toolkit v3 from November 2009.

     

    What is going on?

  • Hmmmm... not sure.  I just got the April CTP up and running and have not had a chance to try out the FindAZip on it yet.  Maybe grab the TransitioningContentControl source code from the Toolkit and add that directly to your project.  Might be able to identify the problem that way.  I will try and get a look at it when I get some free time.

  • Jeff KlawiterJeff Klawiter try { something; } fault { nothing; } catch { everything; } finally { succeed; }

    There is a major bug with the Windows Phone 7 April Refresh that prevents it from loading any code signed assemblies that are not part of the Windows Phone 7 SDK. There is a work around

    http://www.manyniches.com/windows-phone/signed-assemblies-bug-in-the-windows-phone-tools-ctp-refresh/

     

    you have to do this for nearly every control you add outside of the base sdk. Even standard silverlight dlls like System.Windows.Browser.dll

     

    Jeff:

    There is another bug with your app in the new refresh. They got rid of the TopLevelNavigationService property alltogether. I haven't been able to find an alternative so your global error handler breaks.

  • Thanks for the info Jeff! 

     

    For the TopLevelNavigationService... (I don't have the code in front of me - on a different laptop), if it is what I am thinking of, you will have to use the Application.Current.RootVisual and cast it to a PageNavigationFrame and grab the Nav service from there.  That's my guess...

  • Hey Jeff

     

    Nice one! 

     

    But I can't get it to run in my solution. got rid of the signed assemblies bug but I get a senseless XAML parseexception from this line:

    <layout:TransitioningContentControl Content="{TemplateBinding Content}" Style="{StaticResource TransitioningStyle}" />

     

    When I run it, I get this:

    XamlParseException occured

    2024 An error has occurred. [Line: 19 Position: 12]

     

    Parser says this:

    Error    1    [Parser_SetValue_Exception]
    Arguments: System.Windows.FrameworkElement.Style
    Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.50401.0&File=System.Windows.dll&Key=Parser_SetValue_Exception [Line: 144 Position: 39]    C:\Users\Hypi\Documents\Visual Studio 2010\Projects\WinPhoneRSS\WinPhoneRSS\App.xaml    774    9    WinPhoneRSS

     

    when I remove this line, it works but without transitions for sure Wink

     

    u have any clue?

  • I just got the project working under the April CTP.  At this point, I brute forced it by putting the TransitioningContentControl source directly into my project.  I am working on a blog post / screencast to show how to get things working.  I have a couple of other things I want to explore before I finish it up.  Keep an eye here or on my blog - http://slickthought.net for details.  Hopefully in the next day or so...

  • thx jeff, I will keep an eye on it.

  • You can see a quick fix to getting the TransitioningContentControl working with the April CTP here - http://channel9.msdn.com/posts/SlickThought/Windows-Phone-7-April-CTP-and-TransitioningContentControl/

  • Hi Jeff, would either the "brute force" or TransitioningContentControl method for Page transitions be suitable for animating the transition between different orientations of the same Page? For example, fading out the portait view and fading in the landscape view when the phone is oriented into landscape mode?

     

    Thanks!

  • I dont think TCC would do the trick.  I took just a quick look, but an orientation change does not actually change the page content, so the TCC would not be invovled in at all.  It would just behave "as normal".  You would need to wire up the OnOrientationChanged event at the page level and control an animation from there I think.  I want to say Peter Torr has a MIX10 video that shows him doing this.

  • Jeff, you were correct, Peter Torr does have a video covering this. For future reference, it is located here (http://live.visitmix.com/MIX10/Sessions/CL17) at the 10:45 mark. Thanks again!

  • Jeff, one more question concerning TCC, now that I have gotten the AprilCTP workaround implemented and functioning properly within my test application (to do normal page to page transitions). I noticed it works perfectly in portrait orientation. However, when I switch the emulator to landscape and navigate to a different page, the current page is very briefly flashed onto the screen in portrait mode and then the correct animation takes place. This behavior is also noticeable in the demo you posted (to reproduce, note that I had to add landscape support to the Favorites.xaml page).

     

    My guess is this is an artifact of how the TCC actually creates the Page transitions. As it was designed for desktop Silverlight implementations, it did not have to worry about portrait vs. landscape. Of course it could just be an emulator screen buffer issue. Do you have any further thoughts on this? I would feel very hesitant shipping an app if the emulator is a true reflection of how an application with TCC would appear on a device. Thanks!

  • Interesting. I hadnt really noticed it because I was always using the back button to navigate between pages when I was in landscape mode.  Problem when you have a demo app that has TWO WHOLE pages. Wink  I'm not sure what is going on.  It appears to have something to do with sliding content into the various content controls that make up the TCC and the phone having to figure out that the new content should be in landscape rather than portait.  I would lean toward this being a bug in the phone but I have spent about 5 minutes looking at it.  I will try and dig deeper into it tomorrow.

     

     

    UPDATE: Ok, this happens on pages with our without the TCC.  I have sent an email to the dev team to see if this is by design, emulator issue, or bug.

  • Confirmed that the flicker is a known issue and entered as a bug.

  • Hi,

     

    have you had the time to port this all over to the current Beta SDK? There were so many changes that this would help alot Smiley

  • Does it work in the Beta? I followed the video through with the beta, and I can't get it to work at all.

  • For those interested I spent 10 minutes converting it over - not much to change really. Anyway I've updated the project and you can find it on my bog:

     

    http://www.dotnetprofessional.com/blog/post/2010/08/17/Custom-per-page-page-transitions-for-Windows-Phone-7-updated-to-Beta.aspx

     

    Hope this helps out...

  • Hi dotNetProfessional, the link you have posted does not work, could you please give the good link for your zip file.

    Thanks a lot!

  • Sorry about that! Seems I forgot to add the http bit so the Url became relative. I've just fixed it so hopefully it will work now Smiley

  • Hey Jeff,

    Using the simple model you first describe (for a simple 2-page application) I was able to create a nice trasition from MainPage to Page 2. However, intercepting the back button in order to implement the transition in reverse has an unacceptable side-effect. The PhoneApplicationPage_BackKeyPress is used to intercept the navigation and allow the transition; however, the stack comes into play and we're caught in an endless loop between the MainPage and Page 2.

    Is there any way to deactivate the application from code? Intercepting the back button on the MainPage and deactivating thte app, is in effect returning to the normal action that would result from the back button being pressed on the MainPage?

    Alternatively, your second method looks appealing but the Silverlight 3 Toolkit is proving difficult to locate now that Silverlight 4 and the new Silverlight for WP7 are released. Can you provide a link to the older Silverlight 5 Toolkit you used in this video?

    Thanks,

    Greg

  • Karsten Januszewskikarstenj Karsten Januszewski

    Here's how to do this with the latest Silverlight toolkit (November 2010) http://rhizohm.net/irhetoric/post/2010/11/09/Page-Transition-Animations-and-Windows-Phone-7.aspx 

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.