Today I will show how to simply implement a windows phone 7 app that supports orientation with transition. I will also go through a common issue with the list box control.

Setting up the project

For this post I’ll use the default DataBoundApplication, I will also use the transition provided by the brand new Silverlight for windows phone toolkit (second, released in November 2010) : http://silverlight.codeplex.com/releases/view/55034.

Well, let’s do basics. Create a new DataBoundProject :

Default DataBoundApplication
Default DataBoundApplication

First, let’s make our app support the various transition provided by the toolkit. First, add a reference to Microsoft.Phone.Controls.Toolkit and go to the App.xaml.cs file:

[csharp]
// /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 TransitionFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;

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

// Ensure we don’t initialize again
phoneApplicationInitialized = true;
}
//…
[/csharp]

Then edit the main page to support both orientations. Go to the first tag and edit the SupportedOrientation property to PortraitOrLandscape :

[xml]
<!–MainPage.xaml–>
<phone:PhoneApplicationPage
x:Class="WindowsPhoneDataBoundApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!– … –>
[/xml]

Now we have an app that can support orientation and transition. Let’s activate the rotate transition when we change the orientation.

Support rotation on orientation change

I will derive from the PhoneApplicationPage class in order to create a new one that can rotate automatically, and then I will change all my pages for them to derive the new class and thus inherit the new auto-rotation behavior.

So, we need to create our AutoRotatePage class. I override the OnOrientationChange method so when it occurs we perform a rotation transition:

[csharp]
public class AutoRotatePage : PhoneApplicationPage
{
/// <summary>
/// This varialb eis needed in order to now what was the previous orientation
/// and then choose the proper rotation mode
/// </summary>
private Nullable<PageOrientation> _previousOrientation = null;

/// <summary>
/// When the orientation changes perform a rotate transition
/// </summary>
/// <param name="e"></param>
protected override void OnOrientationChanged(OrientationChangedEventArgs e)
{
base.OnOrientationChanged(e);

if (_previousOrientation == null)
return;

RotateTransition transitionElement = new RotateTransition();

// counter clockwise rotation
if (_previousOrientation == PageOrientation.LandscapeRight &&
e.Orientation == PageOrientation.PortraitUp ||
_previousOrientation == PageOrientation.PortraitUp &&
e.Orientation == PageOrientation.LandscapeLeft ||
_previousOrientation == PageOrientation.LandscapeLeft &&
e.Orientation == PageOrientation.PortraitDown ||
_previousOrientation == PageOrientation.PortraitDown &&
e.Orientation == PageOrientation.LandscapeRight)
transitionElement.Mode = RotateTransitionMode.In90Counterclockwise;
// clockwise rotation
else if (_previousOrientation == PageOrientation.LandscapeLeft &&
e.Orientation == PageOrientation.PortraitUp ||
_previousOrientation == PageOrientation.PortraitDown &&
e.Orientation == PageOrientation.LandscapeLeft ||
_previousOrientation == PageOrientation.LandscapeRight &&
e.Orientation == PageOrientation.PortraitDown ||
_previousOrientation == PageOrientation.PortraitUp &&
e.Orientation == PageOrientation.LandscapeRight)
transitionElement.Mode = RotateTransitionMode.In90Clockwise;
// 180 rotation
else
transitionElement.Mode = RotateTransitionMode.In180Clockwise;

var transition = transitionElement.GetTransition((PhoneApplicationPage)(((PhoneApplicationFrame)Application.Current.RootVisual).Content));
transition.Completed += delegate { transition.Stop(); };
transition.Begin();

_previousOrientation = e.Orientation;
}

/// <summary>
/// When leaving the page, clearing the orientation
/// </summary>
/// <param name="e"></param>
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

_previousOrientation = null;
}

/// <summary>
/// When comming to the page, initiate the orientation
/// </summary>
/// <param name="e"></param>
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);

_previousOrientation = Orientation;
}
}
[/csharp]

You may notice that I always keep track of the previous orientation. It is very important because I use it to know if I need to perform a clockwise or a counter clockwise transition. Thus I use the OnNavigatedFrom and OnNavigatedTo method in order to set and clean my previous orientation value. I also do it this way for another reason.
If you are in the main page on a portrait up orientation and then go to the detail view and changhe the orientation to landscape. The detail view will rotate, but when you’ll go back the main page will detect a change in the orientation and then perform an unneeded rotate transition. In order to avoid that, I use the navigation methods to clean the previous orientation variable so that the OnOrientationChange methods can behave properly.

Now, you just need to make your pages derive this new AutoRotatePage class.

[csharp]
// /MainPage.xaml.cs
// …
public partial class MainPage : AutoRotatePage
// …
[/csharp]

Don’t forget the xaml, after declaring the local namespace :

[xml]
<!–MainPage.xaml–>
<local:AutoRotatePage
x:Class="WindowsPhoneDataBoundApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
xmlns:local="clr-namespace:WindowsPhoneDataBoundApplication1"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
shell:SystemTray.IsVisible="True">

<!– … –>

</local:AutoRotatePage>
[/xml]

Now you can compile and test your application. Everything behaves properly.

Rotate transition
Rotate transition

Support a vertical stretch in the ListBox

Now you may want to align right some element of the list box, for example the detail textblock. Let’s do so.

Edit the concerned textblock in the xaml file:

[xml]
<!–MainPage.xaml–>
<!– … –>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}" HorizontalAlignment="Right"/>
</StackPanel>
<!– … –>
[/xml]

You have now a right alignment of your elements:

Right Aligment on portrait
Right Aligment on portrait

But, if you go to the landscape mode, you will find an error in the layout.

right aligment on landscape fails
right aligment on landscape fails

You notice a gap between the detail text and the right border of the screen.

In order to fix this, you will need to create a new resource and apply it to the ListBox. Let’s got the App.xaml and declare it:

[xml]
<!–App.xaml–>
<!– … –>
<Application.Resources>
<Style x:Key="ListBoxTemplate" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentControl ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalContentAlignment="Stretch"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
<!– … –>
[/xml]

As you can see, my resource access to the ListBox items and set the HorizontalContentAlignment to stretch.

Now, apply it to the ListBox:

[xml]
<!–MainPage.xaml–>
<!– … –>
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="MainListBox_SelectionChanged" ItemContainerStyle="{StaticResource ListBoxTemplate}">
<!– … –>
[/xml]

You can go back to the main page on Landscape mode and observe the correct right alignment.

right aligment on landscape ok
right aligment on landscape ok

Wrap up

Now you have everything set to have a nice Windows Phone 7 app that support both orientation with nice transitions and a proper ListBox.

4 thoughts on “Support orientation with a listbox and rotate animation on windows phone 7

  1. Thanks VERY much for this. But you made a mistake. You are rotating the wrong direction. Just reverse the rows 31 and 41 in the AutoRotatePage code and then it is correct. Saved me days/weeks of work with this beautiful and important transition

  2. dude! you are awesomeeeeee!!!!!
    the orientation change list box width adjust problem baffled my partner for several days and we tried like 10,000 solutions, nothing worked but you….

    :* :*
    pure awesomenesss!!!
    thanks a lot!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s