Bring Back Page Transitions to the Windows Phone List Application Template

Url: http://wildermuth.com/downloads/PhoneListWithTr...

Windows Phone 7

The new Windows Phone 7 Tools dropped this week and since I am writing a book on the subject, I decided to upgrade immediately. The upgrade was pretty clean.  I could repeat a bunch of other bloggers with instructions for migrating your projects to the Beta, but go Google it with Bing™ if that's what you need.

As I am writing a book on the subject, I am less dealing with migrating my applicaitons than seeing what has changed.  The first thing I did with the new tools was create a new Windows Phone List Application to see what was new in the way it worked.

For the uninitiated, the Windows Phone List Application is a simple model-driven application that shows a data-bound list of items on a first page and handles navigating to a second page for the details of the individual items. In the CTP version of the template switching pages would cause a page-flip animation to happen that was quite cool to see. The problem was that in the CTP the code that they included in the template was nasty. It was all done at the page level and I am glad to see they removed it.  But to my dismay they didn't replace it with anything.

Since I am in the business of doing demos (as evidenced by the upcoming Silverlight for the Windows Phone classes in Atlanta and Seattle), I wanted something sexier to show aspiring students.  At the same time I wanted to do it in a better way than the old template code did it.

The way that the page-based applications on the Windows Phone work is with a PhoneApplicationFrame class that hosts the application (deriving from the Navigation Framework's Frame class) and each page is an instance of the PhoneApplicationPage class. In the old template, all the transitions were done at the page level. I wanted something better. It seemed to me that if we could hide the transitions in the frame, it would be mostly transparent.  I could have derived from PhoneApplicationFrame do add the transitions, but I thought it was be nicer to use the Silverlight ecosystem to do it right.

To accomplish it, I used styling (at Jeff Wilcox's suggestion) to do the transitions. In the Silverlight Toolkit (remember to use the November 2009 toolkit that is compatible with Silverlight 3), there is a control called the TransitioningContentControl. This control can be used as a traditional content control but allows you to specify the kind of transition that takes place. By overriding the ControlTemplate for the PhoneApplicationFrame, I was able to replace the ContentControl with a TransitioningContentControl:

<Style x:Key="mainFrameStyle"
        TargetType="phone:PhoneApplicationFrame">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="phone:PhoneApplicationFrame">
        <Border x:Name="ClientArea"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Background="{TemplateBinding Background}"
                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                VerticalAlignment="{TemplateBinding VerticalAlignment}">
          <layout:TransitioningContentControl 
                  ContentTemplate="{TemplateBinding ContentTemplate}"
                  Content="{TemplateBinding Content}"
                  Margin="{TemplateBinding Padding}">
          </layout:TransitioningContentControl>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Since Silverlight 3 (which the Phone SDK is based on) does not support implicit styling, we have to apply the style manually. In the Windows Phone List Application project, the frame is created in the App.xaml implementation file (e.g. .cs or .vb file). Inside the InitializePhoneApplication method, I simply added the style to the construction of the frame like so:

// App.xaml.cs
private void InitializePhoneApplication()
{
  if (phoneApplicationInitialized)
    return;

  // Create the frame but don't set it as RootVisual yet; 
  // this allows the splash
  // screen to remain active until the 
  // application is ready to render.
  RootFrame = new PhoneApplicationFrame()
  {
    // Use a style to use the Template 
    // with the TransitioningContentControl
    Style = (Style)Resources["mainFrameStyle"]
  };
  RootFrame.Navigated += CompleteInitializePhoneApplication;

  // Handle navigation failures
  RootFrame.NavigationFailed += RootFrame_NavigationFailed;

  // Ensure we don't initialize again
  phoneApplicationInitialized = true;
}

At this point the transition control worked but the default fadein/fadeout transition was too subtle.  I wanted the page-turn transition.  To do this, I had to override the TransitioningContentControl's template.  Since I was not going to re-use this template, I simply set it as the Template inline in the ControlTemplate for the PhoneApplicationFrame template like so:

<Style x:Key="mainFrameStyle"
        TargetType="phone:PhoneApplicationFrame">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="phone:PhoneApplicationFrame">
        <Border x:Name="ClientArea"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Background="{TemplateBinding Background}"
                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                VerticalAlignment="{TemplateBinding VerticalAlignment}">
          <layout:TransitioningContentControl 
                  ContentTemplate="{TemplateBinding ContentTemplate}"
                  Content="{TemplateBinding Content}"
                  Margin="{TemplateBinding Padding}">
            <layout:TransitioningContentControl.Template>
              <ControlTemplate 
                TargetType="layout:TransitioningContentControl">
                <!-- See example code for complete control template
                     ... -->
              </ControlTemplate>
            </layout:TransitioningContentControl.Template>
          </layout:TransitioningContentControl>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Go grab the code and improve on it.  I am sure its not perfect:

http://wildermuth.com/downloads/PhoneListWithTransitions.zip

 

 

Comments

Gravatar

Sven Thursday, July 22, 2010

This is a pretty neat piece of code, but I've run into a problem with my own application. Unless there's something that *needs* the full width of the screen, elements that have are supposed to stretch across the screen no longer do; instead, the page is only as wide as the widest piece of actual content requires, as if something was set to HorizontalAlignment="Left" somewhere.

I haven't been able to fix this. Any ideas?

Gravatar

Shawn Wildermuth Thursday, July 22, 2010

Sven,

I have some ideas on how to fix this but would like to pursue them. Do you have an example you could e-mail me at shawn (at) wildermuth d0t com?

Gravatar

Shawn Wildermuth Thursday, July 22, 2010

Found the problem. In the TransitioningContentControl, I was binding the Vertical and Horizontal alignments wrong. It should read:

layout:TransitioningContentControl
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"

Gravatar

Sven Thursday, July 22, 2010

Thanks, that worked!

Gravatar

Adi Sunday, August 29, 2010

Hi, this code works brilliantly and your fix, solved the first issue posted by Sven. I do notice another issue though.

When having a combo box, the dropdown list items are all misaligned. For example a combo box with 5 items, will only show 4, as the entire list is being pushed up and the first item will be hidden. Funny thing though, is that even if the list appears to be pushed up by 1 item, clicking on the, say.. 5th item, will trigger the selection for the 4th item.

Gravatar

Felipe Guajardo Friday, September 3, 2010

Thanks man, you rock!
Now, i just need to learn to make my own animations...

Gravatar

Bobby Cannon Saturday, September 11, 2010

This will also cause the page's loaded event to fire when leaving the page.

Any ideas?

Gravatar

Shawn Wildermuth Sunday, September 12, 2010

Bobby,

I haven't run into this as I don't use Loaded since the OnNavigatedTo is more appropriate.

Gravatar

Bobby Cannon Sunday, September 12, 2010

Is more appropriate for? To generic of a statement. :) You assume you know what code I'm putting in the loaded event.

The problem with OnNavigatedTo is the fact that you can't set focus to a control. I use the Loaded event to assign the initial focused control.

The problem comes when navigating away. The keyboard will collapse but when the page load fires again the textbox will get focus so the keybeard will snap back up again then collapse a second time.

This makes the UI really choppy. It could be worse depending on what code is placed in the page Loaded event. We can't begin to guess what someone could code in their loaded event.

Gravatar

Bert Lagaisse Sunday, September 19, 2010

Hi,

Nice peace of code. Just applied it to my app. All goes well until I start going back with the back button. I have used the Loaded event a lot, so when navigating back I run into quite some exceptions.
It's a really nice effect, but I'm in doubt about changing my code so close to the opening of the market.

On that note:
Is using the silverlight toolkit dll's a probem for the certification process ? Visual studio gives a warning.

With kind regards,

Bert Lagaisse

Gravatar

Steven Wednesday, September 22, 2010

hi,
thanks for the post. It is the first one I can actually realy implement!
but I have a problem with my panorama control... is there a known issue?
thanks for the help

Gravatar

John Melville Monday, September 27, 2010

Have you run into a ArgumentException in MS.Internal.XcpImports.CheckHResult(Uint32 hr) when using the back button following adding the page transitions?

Gravatar

self initiative Monday, October 11, 2010

Is there an update for silverlight 4 wp7?

Gravatar

CACuzcatlan Tuesday, October 12, 2010

Thanks for the example! Does anyone know if it's possible to use this pattern to have different animations for navigating forward and backward? The example uses the same navigation for both.

Gravatar

shree Tuesday, January 11, 2011

Hey Shawn Wildermuth,

I have checked the code, but it does not work for me. I have following exception at runtime.
"Invalid attribute value layoutPrimitivesToolkit:AccordionButton for property TargetType. [Line: 19 Position: 12]"


Leave a Comment

*
*
*