Share via


Exercise 1: Introduction to the Windows Phone Navigation Model

In this exercise you will create a new Windows Phone Application project and:

Add appropriate project references

Add an application name as a shared resource string

Edit the main page and add solution folders to hold pages

We will use the Visual Studio 2010 Express for Windows Phone development environment, and will deploy to the Windows Phone Emulator for debugging. The solution we will be working with is based upon the Silverlight for Windows Phone Application template. During development, we will add a Silverlight for Windows Phone project specific item, the Windows Phone Portrait Page.

There is one main Windows Phone Application assembly: Microsoft.Phone.dll. Within this assembly, there two main namespaces to consider:

  • Microsoft.Phone.Controls
  • Microsoft.Phone.Shell

The MainPage.xaml file, like all PhoneApplicationPage items created from the project item template, contains two grids, named TitlePanel and ContentPanel. Also note that the page controls leverage phone-centric style resources defined in App.xaml.

Note:
The steps in this hands-on lab illustrate procedures using Visual Studio 2010 Express for Windows Phone, but they are equally applicable to Microsoft Visual Studio 2010 with the Windows Phone Developer Tools. Instructions that refer generically to Visual Studio apply to both products.

The following section provides a little background information about Silverlight navigation and data binding. If you are familiar with these topics, please skip directly to Task #1.

Note:
The following is a Silverlight navigation overview.

Silverlight for Windows Phone provides the PhoneApplicationFrame and PhoneApplicationPage classes to facilitate navigation to separate sections of content. PhoneApplicationPage controls represent discrete sections of content. The PhoneApplicationFrame acts as a container for page controls, and facilitates navigation to pages. You create as many different pages as needed to present the content in your application and then navigate to those pages from the frame. You can also enable user-friendly URIs by mapping a particular URI pattern to a file that handles the request for that pattern. To create user-friendly URIs, within a frame, you can specify that a certain URI pattern maps to a particular page.

URI mapping enables you to create a URI that is descriptive of the user action instead of a path to a file. A Uri Mapping can include placeholder segments in the URI that will match any value in that segment. You specify a placeholder segment by enclosing the name of the segment with curly braces ( { and } ). The placeholder segment acts as a variable. The URI request is mapped to the first pattern that matches the request. You can use the HyperlinkButton control to enable users to navigate to pages within the application, by setting the NavigateUri property to a URI that maps to a page. Clicking this causes the hosting frame to navigate to the requested page. The target page can then access placeholder-passed parameters from NavigationContext.QueryString.

URI mapping can be used to provide friendlier routes, obfuscate the physical location of the view, and provide a single view to different navigation parameters (like query strings in HTML). In the following example (not related directly to the current lab) you could see how to “hide” the real physical location of the view (“Home”, “About-Us”), how to implement business navigation logic based on provided value (“Page/{number}”), and how to pass query string parameters to the page that could execute different business logic based on them (“Customers{id}”, “Products/{id}”, “Orders{type}&{id}&{date}”):

XAML

<navcore:UriMapper x:Key="TheMapper"> <navcore:UriMapping Uri="Home" MappedUri="/Pages/Views/Default.xaml"/> <navcore:UriMapping Uri="About-Us" MappedUri="/Pages/Views/Misc/About.xaml"/> <navcore:UriMapping Uri="Page/{number}" MappedUri="/Pages/Views/Books/Page{number}.xaml"/> <navcore:UriMapping Uri="Customers/{id}" MappedUri="/Pages/Views/Data/Page.xaml?action=getCustomer&amp;id={id}"/> <navcore:UriMapping Uri="Products/{id}" MappedUri="/Pages/Views/Data/Page.xaml?action=getProduct&amp;id={id}"/> <navcore:UriMapping Uri="Orders/{type}&amp;{id}&amp;{date}" MappedUri="/Pages/Views/Data/Page.xaml?action={type}&amp;orderId={id}&amp;orderDate={number}"/> </navcore:UriMapper>

Note:
The following is a Data Binding overview.

Data binding provides a simple way for Silverlight-based applications to display and interact with data. The way data is displayed is separated from the management of the data. A connection, or binding, between the UI and a data object allows data to flow between the two. When a binding is established and the data changes, the UI elements that are bound to the data can reflect changes automatically. Similarly, changes made by the user in a UI element can be reflected in the data object. For example, if the user edits the value in a TextBox, the underlying data value is automatically updated to reflect that change.

Some common binding scenarios include binding a ListBox to a list of headlines, an input form's TextBox to a customer data object, or an Image to the current user's photo

Every binding must specify a source and a target. The following illustration shows the basic concepts of a binding.

Figure 1

Data binding

The binding engine gets information from the Binding object about the following:

  • The target UI property that displays and possibly allows user changes to the data. The target can be any DependencyProperty of a FrameworkElement.
  • The source object that contains the data that flows between the source and target. The source can be any CLR object, including the target element itself or other UI elements. If the target is in a data template, the source can be the UI element to which the template is applied.
  • The direction of the data flow. The direction is specified by setting the Mode property on the Binding object.
  • The optional value converter that applies to the data as it is passed. The value converter is a class that implements IValueConverter.

For example, the Foreground property of a TextBox can be bound to a SolidColorBrush so that the color of the text can change based on the data. In this scenario, the Foreground property is the target, and the SolidColorBrush object is the source for the binding.

A data template allows you to specify how data is displayed. For example, your object might contain an image and a string. You could define the data template to display the string on the right of the image, the left, or overlay the image. You can add margins between the image and text, a border, or background color with data templates. In addition, you can apply the same data template to all the objects in your collection when using an ItemsControl (like ListBox).

Task 1 – Creating a Windows Phone Application Project in Visual Studio

During this task you will create a new Windows Phone Application and explore its structure.

Note:
If you are already familiar with creating new projects using Visual Studio, or you went through any of the other Windows Phone labs, you can create a new Windows Phone Application project named WindowsPhoneNavigationAndControls, skip the following steps and go directly to the next task.

  1. Open Microsoft Visual Studio 2010 Express for Windows Phone or Visual Studio 2010.
  2. In the File menu, choose New Project. In theNew Project dialog, select the Silverlight for Windows Phone category in the list of installed templates, and there the Windows Phone Application template. Set the name to Begin and the location to Ex1-IntroductionToPhoneNavigationModel in the Source folder of the lab. Make sure the solution name is Begin, and then click OK. Choose Windows Phone 7.1 when you are asked.
  3. Open MainPage.xaml and locate the TitlePanel and change the text value of the ApplicationTitle and the PageTitle elements as shown below:

    XAML

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="Main Page" Margin="-9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>

  4. Open App.xaml, and locate the section named Application.Resources. Add the following highlighted code below.

    XAML

    <Application.Resources> <system:String x:Key="AppName">CONTROLS &amp; NAVIGATION</system:String> </Application.Resources>
  5. Now add the following marked xml namespaces:

    XAML

    <Application
    FakePre-626a8887af1e4ca581eb6f49b1e58dd5-fc7c8fee80984790a82de4463a2ed39dFakePre-5de5903325124e098b382d7e4ade76d7-05999f0e23904d559eafad7e3c682724FakePre-20c0fcc60c8e4fc89a808892668496a2-3a9b79575e3a44119976628d77617df2FakePre-29b5be7b43344d5ba28b257d204b9c25-74747d08caa54e3cbe4a864cb8b5eb54FakePre-32c6730c1af04fcf8a98087e6c2fe459-44a782b5cf024b8b80c24ba23ae8048bFakePre-9b5f277c74774784942cd20c16c41b1b-60d83e56533840b39b0fea96b402ea21FakePre-fb15ee5fa6c4477ca4142fbef9ee5c21-84495a103c4445a18ebb314c5ed0e435FakePre-48deb2d54e6c4ebfb47404c16e7c5397-8d52620a5fa341db90807b42e614cfa6FakePre-7e10c49fe37d4c02b9e0388fc12b6a55-3016b0ccb56e45e89010ff8cc5a3bc83FakePre-986c03c3a87e42429da249ebb2d236ad-71d0e95986134156930e2fdd0efdcb1aFakePre-d24c30ecca2048ccb0045cf5c77e4e95-2f32f32a3b1342af94748ad1627fea8d
  6. Press F5 to launch the application in the Windows Phone Emulator. Notice that a device emulator window appears and there is a pause while Visual Studio sets up the emulator environment and deploys the image. Once it is ready, the emulator shows the Start page and shortly thereafter, your application appears in the emulator window.

    Figure 2

    Running the application in the Windows Phone Emulator

  7. Until you create the user interface and program the application logic, there is very little that you can do with the application. Press SHIFT + F5 or click the Stop button in the toolbar to detach the debugger and end the debugging session. Do not close the emulator window.

Task 2 – Adding Pages and Navigating between them

In this task you will add some pages and modify them. These pages will be used later for playing back selected music and video files, displaying Web content, etc. Following this, we will add Navigation support to the application along with a HyperlinkButton to the MainPage for accessing navigation.

The Application.RootVisual (located in App.xaml file) is a PhoneApplicationFrame – it will contain a collection of UriMappings which we will add in this exercise.

  1. Create a new project folder and call it Views.
  2. Under the Views project folder, create an additional folder called Music.
  3. Add a new portrait page to the newly created Music folder and name it Default.xaml.
  4. In the XAML page, locate the TitlePanel section and change it to following:

    XAML

    <Grid Grid.Row="0" x:Name="TitlePanel" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationName" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="ListName" Text="Music" Style="{StaticResource PhoneTextTitle1Style}"/> </Grid>

  5. Follow steps 2 through 4 to create an additional page under the Video folder.
    Note:
    The page name should be Default.xaml as well, but the text on page should be “Videos” instead of “Music”. Also, the folder name created in step 2 should be “Video”.
  6. Follow steps 2 through 4 to create an additional page under the About folder.
    Note:
    The page name should be Default.xaml as well, but the text on page should be “About” instead of “Music”. Also, the folder name created in step 2 should be “About”.
  7. Follow steps 2 through 4 to create an additional page under the DeadEnd folder.
    Note:
    The page name should be Default.xaml as well, but the text on page should be “Dead End” instead of “Music”. Also, the folder name created in step 2 should be “DeadEnd”.
  8. Modify the About page by adding the following markup inside ContentPanel.

    XAML

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock TextWrapping="Wrap" Margin="5" Style="{StaticResource PhoneTextNormalStyle}" Text="This is a sample Windows Phone 7 navigation application. All rights reserved to you - you, the writer of this lab!"/> </Grid>

  9. Open App.xaml, and add the following style named PhoneHyperlinkStyle.

    XAML

    <Application.Resources> <system:String x:Key="AppName">CONTROLS &amp; NAVIGATION</system:String> <!-- Hyperlink style --> <Style x:Key="PhoneHyperlinkStyle" TargetType="HyperlinkButton"> <Setter Property="Margin" Value="30,10,0,10"/> <Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}" /> <Setter Property="HorizontalAlignment" Value="Left" /> </Style> </Application.Resources>

  10. Open App.xaml file and locate the Application.Resources element and add the UriMapper object as follows. This will define a UriMapper object that will be used through the entire application for all navigation purposes.

    XAML

    <Application.Resources> ... <nav:UriMapper x:Key="UriMapper"> <nav:UriMapper.UriMappings> <nav:UriMapping Uri="/Music/{song}" MappedUri="/Views/Music/Default.xaml?Song=Assets/{song}"/> <nav:UriMapping Uri="/Video/{video}" MappedUri="/Views/Video/Default.xaml?Video=Assets/{video}"/> <nav:UriMapping Uri="/WebBrowser/{defaultURL}" MappedUri="/Views/WebBrowser/Default.xaml?DefaultURL={defaultURL}"/> <nav:UriMapping Uri="/Pictures" MappedUri="/Views/Pictures/Default.xaml"/> <nav:UriMapping Uri="/DeadEnd" MappedUri="/Views/DeadEnd/Default.xaml"/> <nav:UriMapping Uri="/PictureView/{picture}" MappedUri="/Views/Pictures/PictureView.xaml?Picture={picture}"/> <nav:UriMapping Uri="/About" MappedUri="/Views/About/Default.xaml"/> </nav:UriMapper.UriMappings> </nav:UriMapper> </Application.Resources>

    Note:
    Here the URI mapping is used to “hide” real navigation structure and provide query string parameters to the pages.

  11. For the UriMapper object to be used through the application you now need to set the object in the Resources dictionary to the application’s RootFrame. Right-click App.xaml in Solution Explorer and choose View Code to open its code-behind file. Add the following blue-highlighted line to the class constructor:

    C#

    public App() { // Global handler for uncaught exceptions. UnhandledException += Application_UnhandledException; ... // Standard Silverlight initialization InitializeComponent(); // Phone-specific initialization InitializePhoneApplication(); this.RootFrame.UriMapper = Resources["UriMapper"] as UriMapper; }
    Note:
     The Application Resources can be accessed from code as a string-keyed dictionary, using the x:Key property (in this case “UriMapper”) as the access key.

  12. Open the MainPage.xaml file to add some hyperlink buttons on the application’s main page. These will lead to the various pages we have previously added. Locate the ContentPanel grid and change its contents to the following:

    XAML

    <ScrollViewer BorderBrush="Transparent"> <StackPanel Margin="5"> <TextBlock Text="Music" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/Music/Music1.mp3" Content="Song #1" Style="{StaticResource PhoneHyperlinkStyle}" /> <HyperlinkButton NavigateUri="/Music/Music2.mid" Content="Song #2" Style="{StaticResource PhoneHyperlinkStyle}" /> <TextBlock Text="Videos" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/Video/Video1.wmv" Content="Video #1" Style="{StaticResource PhoneHyperlinkStyle}"/> <HyperlinkButton NavigateUri="/Video/Video2.wmv" Content="Video #2" Style="{StaticResource PhoneHyperlinkStyle}"/> <TextBlock Text="Stack Manipulation" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/DeadEnd" Content="Dead End" Style="{StaticResource PhoneHyperlinkStyle}"/> <TextBlock Text="About" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/About" Content="About" Style="{StaticResource PhoneHyperlinkStyle}"/> </StackPanel> </ScrollViewer>
  13. Compile and run the application. Click hyperlinks to ensure that everything works correctly.

    Note:
    Use the Back button to get back to the applications’ main page.

    Figure 3

    Running the solution

Task 3 – Manipulating the navigation stack

There are times when you would need to change the application’s navigation stack. This can be done by removing previously visited pages from the stack, as we will demonstrate in this task.

We will change the “Dead End” page so that when the user navigates to it, the previous page on the navigation stack (the application’s main page) will be removed. This will cause the application to terminate once the user tries to back out of the “Dead End” page, since it will be the only page in the navigation stack.

  1. Open the Default.xaml.cs file under the Views\DeadEnd project folder.
  2. Add the following override to the Default class:

    C#

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { NavigationService.RemoveBackEntry(); base.OnNavigatedTo(e); }

    See how we simply call NavigationService.RemoveBackEntry to remove the topmost page from the navigation stack. To remove multiple pages we would need to call this method multiple times. Also note that trying to remove an entry if the navigation stack is empty will result in an exception. You may use the NavigationService.CanGoBack property to see if there are pages to remove inside the navigation stack.

  3. Compile and run the application. Navigate to the “Dead End” page and then try to back out of it. This should cause the application to terminate.

    This step concludes the first exercise. During this exercise you created a simple Windows Phone Silverlight application, added multiple pages to this application and created navigation between those pages. You also saw how to manipulate the phone’s navigation stack. In the next Exercise, you will add user controls to the created pages.

    Note:
    The solution for this exercise is located at the Source\Ex1-IntroductionToPhoneNavigationModel\End folder of this lab.