I have created a video of the application.
Contents
Introduction
With the growing excitement around Windows Phone 7 and Daniel writing Windows Phone 7 Unleashed, I couldn’t resist getting involved in the space. After all, I have the advantage of an early preview of Daniel’s book. So I downloaded the tools and started playing around. I wanted to explore the Panorama and Pivot controls, and came up with a neat demo application that uses Netflix data, and showcases the Pivot and Panorama controls as well as OData
, page navigation, WrapPanel
and more. This article will be in part an overview of the Panorama and Pivot controls, and in part a walkthrough of the demo application.
Note: As I worked through the article, the number of pages kept growing and so I have split the article into two parts. Part 2.
Background
The final Windows Phone Developer Tools have been released, and with that, among other things, we have the official release of two navigation controls: the Pivot & Panorama. These controls are vital to the visual user experience on Windows Phone, and the phone's built-in applications use them extensively. Thus, undoubtedly, you will find yourself using them a lot. This is not to say, however, that they are a suitable choice for all applications. As these controls are quite new and unique to Windows Phone (at least currently), there may be some confusion in understanding them. There are several resources available. The particularity useful ones include: Windows Phone Design Days – Pivot and Panos video presented by Amy Alberts and Chad Roberts, and the UI design and interaction guide for Windows Phone 7. I will be drawing on these resources in the overview below.
Prior to the official Microsoft release of these controls, there were some alternatives such as Stephane Crozatier’s Panorama & Pivot controls available on Codeplex. For those who built their applications with these early controls, the advice is to migrate to the official controls. Fortunately, Stephane Crozatier has written a transition guide.
What Will be Covered
- Panorama Control
- Pivot Control
- String Formatting
- Consuming Odata (part 2)
- Page Navigation (part 2)
- Progress Bar (part 2)
- WrapPanel (part 2)
The Demo Application
The demo application is a Panorama application that allows users to browse through Netflix data. At the top layer, the user is presented with a list of genres, new releases and highest rated movies. The user can then drill down into each movie to get movie details. Selecting a genre from the genre list will take the user to a Pivot, which lists movies for the selected genre; representing the data in three different ways: all movies for that genre, movies sorted by year, and movies sorted by average rating. In an ideal situation, I would like to see the list of all genres to be only the top level genres instead of a very long list of genres and subgenres, but there wasn’t an easy way of querying this.
Prerequisites
- Windows Vista or Windows 7
- Windows Phone 7 Developers Tools which includes Visual Studio Express 2010 for Windows Phone, Windows Phone Emulator, Expression Blend 4 for Windows Phone, and XNA Game Studio 4.0
- Visual Studio Express 2010 and Expression Bled 4 will only be installed if you do not already have them installed
- If you have previously installed the Beta Tools, you will have to uninstall it before installing the final tools. Note that the installation may take some time. Leave the installation running, it will eventually complete.
- Silverlight for Windows Phone Toolkit
- OData Client Library for Windows Phone 7 (the one currently available is from March 2010)
Understanding the Pivot and Panorama Controls
The Pivot and Panorama are two layout controls that help you represent data on the phone in a unique way. They have several things in common. They both hold a number of horizontally arranged individual views (sections). They are visually quite similar; both show a bit of the off-screen content, have titles and section titles (see Figures 1 and 2). Both controls have built-in touch navigation that allow the user to navigate left to right between the different sections using the pan and flick touch-gestures, and up and down touch gestures for when the section’s content doesn’t fit into the height of the screen boundaries. The left to right navigation is cyclical (i.e. after the last section, the first section appears).
The controls are also quite different. This is mainly because they each serve a different purpose. The Panorama is meant to entice the user to explore; whereas the Pivot is about tasks and getting something done. As Amy Alberts and Chad Roberts say in their presentations, Pivots are efficient, focused, habitual whereas the Panorama is expansive, dynamic, inviting exploration. We can see this differentiation in Figure 1 and 2, where the Panorama offers a visually appealing experience, enticing the user with an attractive background, large title, variety of UI controls, animation, thumbnails, etc, while the Pivot appears less appealing. There is also one other difference, and that is the content width of each view. The Panorama views usually span over screen boundaries, whereas the Pivot content is confined to the screen width; fitting within the screen. Users can navigate through the pivot sections not only via the left to right gestures, but also by directly selecting the Pivot Title.
Panorama
The Panorama is a wide horizontal canvas that spans over screen boundaries. The canvas is sliced into several different views and uses layered animations and UI controls to represent data in different ways, i.e., lists, grids, buttons, etc. For usability issues, the number of these sections should be limited to four, but the width and height of each section can vary. The panorama tends to be explorative, essentially working as the top layer to several other experiences. As the Panorama is intended to coax the user to explore, it should show content that is interesting, tailored for that user; it should not feel generic. We should also not want to overwhelm the user with too much data. As Jeff Wilcox says “Panorama is meant to be the starting space, think white space not tons of data”. The Panorama contains data, and links that take the user to more detailed pages of the content, for example to the Pivot. The user then transits from the exploratory mode of the Panorama to the more focused mode of the Pivot.
Figure 1: Panorama
As you can see in Figure 1, some pixels of the next section are showing to the right. This is to hint the user that there is more content to explore. A Panorama application should offer a visually appealing experience. This can be achieved with an attractive background. It can be either a single colour or a background image. According to the design guidelines, the image size should be 800 pixels high and 480 to 1000 pixels wide. The image could possibly be wider but no more that 2000 px as the image will be clipped at this width. Note that an image with a height of less then 800 pixels will be stretched to that height without constraining proportions. The background image is the bottom layer of the Panorama with the different sections overlaying on top of it. You should not attempt to have the background dependent on the content because they are not going to match up. As you can see in the video, the Panorama title moves in different rate then its section titles as the user moves thought the Panorama.
Pivot
Some regard the pivot being a lot like the TabControl
for the phone. The pivot also has several different views (sections). It is recommended to limit the number of sections to 7 to ensure users can comprehend what is presented to them.
Unlike with the Panorama where the content may go beyond the screen boundaries, the Pivot content is confined to the screen width. Also, contrary of the Panorama, the Pivot doesn’t display the few pixels of the content of the next section, but rather gives users an indication how the data is filtered through the section titles at the top of the screen (See Figure 2).
Figure 2: Pivot
As we said before, Pivots are about getting something done, and so Pivots are suited to have an ApplicationBar
. This is contrary to Panorama based applications which should not show an ApplicationBar
. Therefore, if your page needs an application bar, use a Pivot instead of a Panorama. Pivots are designed to represent data or items of similar type. For example, pivots can be used as filters for similar content around the same task flow. A good example of a pivot is the Email application, which shows all emails in one view, flagged emails in another, unread email in another, etc.
Things to Avoid
You should not place a Pivot inside a Panorama, or nest Pivots. Also you should not attempt to use either the Pivot or Panorama for creating a wizard flow. As Amy Alberts says, the user sees Panoramas and Pivots as distinct areas of data being surfaced to them, and not as a flow of UI that the user walks through. So for a wizard, use a page flow instead. It is also recommended not to use a map control inside a Pivot or Panorama. You should also avoid animating the panorama title or section titles as they are going to be moving as the user moves through the control. Also avoid dynamically changing the Panorama title. The UI guidelines also state not to override the horizontal pan and flick functionality because it collides with the interaction design of the controls. Also keep to the recommended number of views, seven for Pivot and four for Panorama. And keep in mind that the user should never lose his or her place inside the Panorama, and should always know how to get back. You would also not want to have a Panorama, and every link on the Panorama, taking you to a Pivot.
The Demo Application: Getting Started
Both controls have custom templates that you can use to create the Pivot or Panorama. You can either create a new Pivot or Panorama Application Project or, for an existing project, you can add a new Pivot or Panorama Page. We will demonstrate both ways. Both controls can also be added through Visual Studio into the Toolbox and then dragged onto a page.
We begin by creating a new Panorama Application Project. In Visual Studio go File -> New -> Project and select Windows Phone Panorama Application found under the Silverlight for Windows Phone option (see Figure 3).
Figure 3: Create a new Windows Phone Panorama Application
Once the project is created, we can see that the template provided us with a project structure, some sample data, and formatted views for the Panorama. Visual Studio also provides us with a nice feature to view the panorama sections in the designer. The designer will show the currently selected panorama item xaml (see Figure 4).
Figure 4: Panorama in Visual Studio designer.
The Phone application template also comes with the following default images:
- Application icon (ApplicationIcon.png)
- The application icon is used in the quick launch screen.
- Background image of an application Tile (background.png)
- The application Tile is displayed for a quick launch on the start experience, once the user has pinned it there. You can pin the application to the start experience in the emulator by pressing the application icon in the quick launch screen. After a second or two, you should get a context menu with the option to either pin to start or uninstall (see Figure 6). The Tile title and background image can be set in application properties as shown in Figure 5. You will be able to change the Tile title, its background image, and a counter through Tile Notification to create a personal experience for the user, but this is beyond the scope of this article.
- Splash screen (SplashScreenImage.jpg)
- The splash screen is shown before the application gets to the first page. There are some rules for creating the splash screen such as the width and height of the image has to be 480 x 800 pixels, the image name must be SplashScreenImage.jpg and the Build Action property must be set to
Content
.
Figure 5: Set Application title, icon, Tile title and Tile background image
Figure 6: Pin application to the start screen
Panorama Control
Working with the Panorama control is straight forward. The excerpt shown below is taken from the Panorama application template. As we can see, the Panorama control holds two PanoramaItem
content controls. The PanoramaItem
controls host the panoramic content, and these are the views or sections we talked about in the overview above. As per the recommendations, there should not be more than four PanoramaItem
controls within a Panorama
control. In the demo, we use three. Although we do not use this in the demo, the PanoramaItem
controls can be added and removed programmatically at runtime. The Panorama
control contains a Title
and a Background
property. The Title
in the excerpt below is specified as text, but it has a TitleTemplate
dependency property and thus can also be set through data binding. This also applies to the Header
property of the PanoramaItem
. As you can see below, the panorama background is applied as an image with an ImageBrush
, and we use the same in the demo, but you can also use GradientBrush
or SolidColorBrush
. If you use a background image, its Build Action should be set to Resource
to ensure that it is shown as soon as the first page of the application starts. Setting the Build Action to Content
means that it gets loaded asynchronously. Note in the excerpt below that all left and right margins of the panorama
items are set to 12px
. This is for UX reasons and applies to the Pivot control too.
<controls:Panorama Title="my application">
<controls:Panorama.Background>
<ImageBrush ImageSource="PanoramaBackground.png"/>
</controls:Panorama.Background>
<controls:PanoramaItem Header="first item">
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap"
Margin="12,-6,12,0"
Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
<controls:PanoramaItem Header="second item">
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<Rectangle Height="100" Width="100" Fill="#FFE5001b"
Margin="12,0,9,0"/>
<StackPanel Width="311">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap"
Margin="12,-6,12,0"
Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
</controls:Panorama>
For the demo application, I modified the sample Panorama
control. I changed the Panorama Background, and Title, modified the PanoramaItem
layout, set the PanoramaItem
Headers, and replaced the binding expressions. I also defined a new PanoramaForegroundBrush
. The TextBox Foreground
styles that are used in the Panorama
template provide automatic support for the phone dark and light themes. The behaviour is that the text within the Panorama
is white under the dark theme and changes to black under the light theme. The black text didn’t work with the Panorama
background and so I defined a new PanoramaForegroundBrush
, and set the Foreground
Property of each TextBlock
within the Panorama
control to the new brush.
<UserControl.Resources>
<SolidColorBrush x:Key="PanoramaForegroundBrush" Color="#FFf6f0d9"/>
</UserControl.Resources>
The first Panorama
section shows a list of all genres. We set the section Header
to 'genres
' and use a ListBox
control to allow the user to navigate vertically through the list (see below).
<controls:PanoramaItem Header="genres" >
<ListBox x:Name="GenreListBox" Margin="0,0,-12,0"
ItemsSource="{Binding Genres}"
SelectionChanged="GenreListBoxSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextLargeStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
The second Panorama
section shows new releases. The information is depicted as a small thumbnail of the movie, together with a title, average rating, and a date that the Dvd is available from. Again, we set the Header
and use the ListBox
control to layout the content (see below).
<controls:PanoramaItem Header="new releases" >
<ListBox Margin="0,0,-12,0" x:Name="NewTitlesListBox"
ItemsSource="{Binding NewTitles}"
SelectionChanged="TitlesListBoxSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<Image CacheMode="BitmapCache" Source="{Binding BoxArt.LargeUrl}"
Margin="12,0,9,0"/>
<StackPanel Width="311">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextLargeStyle}"/>
<StackPanel Orientation="Horizontal" >
<TextBlock Margin="12,5,5,5" Text="Rating:"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Margin="0,5,0,5" Text="{Binding AverageRating}"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="12,5,5,20" Text="Available: "
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Margin="0,5,0,20" Text="{Binding Dvd.AvailableFrom,
Converter={StaticResource StringFormatConverter},
ConverterParameter=\{0:d MMMM yyyy\}}"
TextWrapping="Wrap"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem
String Format Converter
In the second PanoramaItem
, there is a date field which required formatting. In Silverlight 4, you can specify string
formatting directly in the Binding
expression, but because Windows Phone is based on Silverlight 3, we need to use a Converter
. Luckily, Daniel wrote such a converter some time ago, and so I have incorporated his StringFormatConverter
class in my demo. Thank you darling. To use the StringFormatConverter
class, add a namespace
reference in the MainPage.xaml, like so:
xmlns:converter="clr-namespace:NetflixBrowser.Helpers"
Add the converter as a resource as shown below:
<UserControl.Resources>
<converter:StringFormatConverter x:Key="StringFormatConverter" />
</UserControl.Resources>
Specify the ConverterParameter
attribute to define the format:
<TextBlock Margin="0,5,0,20" Text="{Binding Dvd.AvailableFrom,
Converter={StaticResource StringFormatConverter},
ConverterParameter=\{0:d MMMM yyyy\}}"
TextWrapping="Wrap"
Foreground="{StaticResource PanoramaForegroundBrush}"
Style="{StaticResource PhoneTextNormalStyle}"/>
Pivot Control
We add the Pivot control as a new Pivot Page. In the Solution Explorer, right click on the project, navigate to Add -> New Item, and select Windows Phone Pivot Page (see Figure 7).
Figure 7: Add a new Windows Phone Pivot Page
The following excerpt shows the pivot control template. We can see many similarities with the Panorama
control. Just like the Panorama
control, the Pivot Control holds PivotItem
content controls. It has a Title
and a Background
. The Title
can be set as text or it can be databound
, just like with the Panorama Control. Again, this is true for the PivotItem
Headers. The Pivot
can also have its background set to an image. We do not set the Pivot Background
property in the demo application, and thus the Pivot
background behaves according to the dark or light theme set on the phone (which means that it will be either black or white).
<controls:Pivot Title="MY APPLICATION">
<controls:PivotItem Header="item1">
<Grid/>
</controls:PivotItem>
<controls:PivotItem Header="item2">
<Grid/>
</controls:PivotItem>
</controls:Pivot>
In the demo application, we use the Pivot
control to show movies for a selected genre. The Pivot
page is called GenreDvds.xaml. Just like with the Panorama
control, I modified the template, changing the Pivot
title, headers, etc. Because the GenreDvds.xml page is being navigated to from the Panorama
page, displaying DVDs for the selected genre, I set the Pivot Title with a Binding
expression as shown below:
<controls:Pivot x:Name="SelectedGenre" Title="{Binding SelectedGenreName}"
Visibility="{Binding Loaded,
Converter={StaticResource BooleanToVisibilityConverter},
ConverterParameter=Visible}">
.
.
.
</controls:PivotItem>
In the above excerpt, you can also see that we are dynamically setting the Pivot’s visibility. This will be covered in Part II of this article under the section called Progress Bar.
The Pivot
control has three sections. All three sections are layed out in the same way depicting the movie thumb image, title, short synopsis, average rating and availability.
<controls:PivotItem Header="all">
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding GenreTitles}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<Image CacheMode="BitmapCache" Source="{Binding BoxArt.LargeUrl}"
Margin="12,0,9,0"/>
<StackPanel Width="311">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap"
Style="{StaticResource PhoneTextLargeStyle}"/>
<TextBlock Text="{Binding ShortSynopsis}" TextWrapping="Wrap"
Margin="12,-6,12,10"
Style="{StaticResource PhoneTextSubtleStyle}"/>
<StackPanel Orientation="Horizontal" >
<TextBlock Margin="12,5,5,5" Text="Rating:"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Margin="0,5,0,5" Text="{Binding AverageRating}"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="12,5,5,20" Text="Available: "
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Margin="0,5,0,20"
Text="{Binding Dvd.AvailableFrom,
Converter={StaticResource StringFormatConverter},
ConverterParameter=\{0:d MMMM yyyy\}}"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PivotItem>>
Conclusion
In this article, we explored the Pivot
and Panorama
controls, introduced the demo application, saw how to add the controls to your project, and had a look at the Pivot
and Panorama
templates. In part II of this article, we will cover OData
, WrapPanel
, Page Navigation, and the Progress Bar. I hope you found this article useful. If you enjoyed my article, please rate it and maybe share your thoughts below.
History
- October 2010: Initial release
References