Understanding Page Orientation in Silverlight for Windows Phone

At MIX this year, Silverlight developers were handed a real treat: their first look at Silverlight for Windows Phone. Silverlight is the primary platform that developers will use to write applications for the new Windows phone, which will debut later this year. I can’t remember being this excited about a platform since…well, since Silverlight 1.0. If you’re an iPhone user like me, and you’d love to write iPhone apps but don’t care for Objective-C (soooooo 1990s!), Silverlight for Windows Phone is the hottest thing since color TV. Just think: you can leverage the skills you acquired writing Silverlight apps for the browser to write Silverlight apps for phones. You already know 90% of what you need to know; all you have to do is learn about the relatively few differences between Silverlight for the browser and Silverlight for the phone.

One of those differences is page orientation. When you write browser-based (or out-of-browser) Silverlight apps, you don’t have to worry about a user turning his or her monitor on its side. The phone, of course, is different. Silverlight for Windows Phone introduces the concept of page orientation, which tells you whether the phone is upright, upside-down, or on its side. Most apps don’t have to do much to rotate the entire display when the phone itself rotates; Silverlight does that for them. But some apps will need to know when the phone has rotated so they can customize the UI programmatically.

To demonstrate, I built a simple app that displays Dooby the Penguin:

Portrait 

When you create a new Silverlight for Windows Phone application, Visual Studio includes the following line of code in MainPage’s constructor in MainPage.xaml.cs:

SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;

This tells the runtime that the application supports both portrait and landscape orientations, and when the phone is rotated onto a side, Silverlight automatically rotates the display:

Landscape Rotated

When you design a Silverlight for Windows Phone application that supports portrait and landscape modes, you strive to create a XAML UI that produces the look you want in either orientation without code intervention. In this example, because the penguin is positioned inside a Grid cell, it is automatically centered in the display whether the phone is upright or on its side.

If you don’t want the display to rotate when the orientation changes, you can remove Landscape from the page’s supported orientations:

SupportedOrientations = SupportedPageOrientation.Portrait;

Now turning the phone on its side will produce this:

Landscape Unrotated

The more interesting case is when code intervention is required to achieve the look you want when the orientation changes. For example, suppose you want to display one penguin in portrait mode, but two penguins in landscape mode:

Landscape Customized 

If SupportedOrientations is SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape (or simply SupportedPageOrientation.PortraitOrLandscape), the page fires an OrientationChanging event when a turn begins and an OrientationChanged event once the turn is complete. You can use these events to modify the XAML UI. For example, I structured my XAML this way to display one penguin in portrait mode and two in landscape mode:

<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

    <!–TitleGrid is the name of the application and page title–>

    <Grid x:Name="TitleGrid" Grid.Row="0">

        <TextBlock Text="ORIENTATION DEMO" x:Name="textBlockPageTitle"

            Style="{StaticResource PhoneTextPageTitle1Style}"

            HorizontalAlignment="Center"/>

    </Grid>

    <!–ContentGrid is empty. Place new content here–>

    <Grid x:Name="ContentGrid" Grid.Row="1">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*" />

                <ColumnDefinition Width="0" x:Name="SecondColumn" />

            </Grid.ColumnDefinitions>

            <local:PenguinUserControl Grid.Column="0" />

            <local:PenguinUserControl Grid.Column="1"

                Visibility="Collapsed" x:Name="SecondPenguin" />

        </Grid>

    </Grid>

</Grid>

Then I did this in the code-behind:

public partial class MainPage : PhoneApplicationPage

{

    public MainPage()

    {

        InitializeComponent();

        SupportedOrientations = SupportedPageOrientation.Portrait |

            SupportedPageOrientation.Landscape;

         this.OrientationChanged +=

             new EventHandler<OrientationChangedEventArgs>(OnOrientationChanged);

    }

 

    void OnOrientationChanged(object sender, OrientationChangedEventArgs e)

    {

        if ((e.Orientation & PageOrientation.Landscape) != 0)

        {

            SecondPenguin.Visibility = Visibility.Visible;

            SecondColumn.Width = GridLength.Auto;

        }

        else // Portrait

        {

            SecondPenguin.Visibility = Visibility.Collapsed;

            SecondColumn.Width = new GridLength(0);

        }

    }

}

The Orientation property of the OrientationChangedEventArgs passed to the event handler is a PageOrientation object, which is defined this way in the Silverlight for Windows Phone runtime:

public enum PageOrientation

{

    Landscape = 2,

    LandscapeLeft = 0x12,

    LandscapeRight = 0x22,

    None = 0,

    Portrait = 1,

    PortraitDown = 9,

    PortraitUp = 5

} 

It follows that you can determine exactly what the phone’s orientation is (upright, upside-down, on its left side, or on its right side) by comparing e.Orientation to specific values such as PortraitUp and LandscapeRight. But the more common case is that you simply want to know whether the phone is oriented vertically or horizontally. You can check for the latter by ANDing e.Orientation with Landscape and checking for a nonzero value. That’s precisely what I’m doing in the OnOrientationChanged method above.

Interestingly enough, you can’t determine the phone’s orientation by checking the ActualWidth and ActualHeight properties of the Silverlight control or any other control; these properties don’t change when the orientation changes. (That’s how it works in the Silverlight for Windows Phone CTP, anyway; I can’t guarantee that will be the case in the final version.) Nor does there appear to be any way to determine what the phone’s orientation is at startup. However, if the application starts up in landscape mode, the page immediately fires its OrientationChanging and OrientationChanged events, so you can design your UI to assume that the application starts up in portrait mode and let your event handlers adjust the display if in fact it starts up in landscape mode.

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X