Navigating around windows phone 7

Vermeer-the-Astronomer

Navigation in Silverlight applications for Windows Phone is simpler, if somewhat more constrained, than in Silverlight applications for the web. 

In classic Silverlight applications the template on which we build our pages is the UserControl.  User controls are set as the root visual for the applications and, at least before Silverlight 3, navigation was typically handled by replacing one user control with another.

Silverlight 3 introduced a special navigation control.  While the root visual for a Silverlight application was still a user control, the user control could host a navigation “Frame”.  The frame, in turn, hosts “pages”, which are just specialized user controls.

Silverlight for Windows Phone adopts the navigation scheme exemplified by the latter set of classes: frames and pages.  It also simplifies it.  Instead of hosting the navigation frame in a page, a specialized class called a PhoneApplicationFrame is the root visual in a WP7 application.  It, in turn, hosts a variety of PhoneApplicationPages.

It is helpful to think of the PhoneApplicationFrame as a web browser.  Like a web browser, it never changes when you move between pages.  Instead it acts as a viewer for the pages you want to navigate between.  You navigate between pages, in turn, simply by passing a uri to the browser.

The PhoneApplicationFrame is typically set in the app.xaml file (though it can also be set programmatically).  The Source attribute of the frame is set to the uri for the initial PhoneApplicationPage.

<Application.RootVisual>
        <phoneNavigation:PhoneApplicationFrame 
        x:Name="RootFrame" 
        Source="/MainPage.xaml"/>
    </Application.RootVisual>

So how do we navigate between different pages in our application? 

1. One way is to simply use a HyperlinkButton control.  The NavigateUri attribute can be set to the location of another PhoneApplicationPage (in this case, the MyView page in the root of my application).  When the user clicks on the link, the root frame will navigate to the new page. 

<HyperlinkButton Content="HyperlinkButton"  
                     Name="MyViewLink"
                     NavigateUri="/MyView.xaml" />

You will want to include the initial slash in your path.  If you don’t, the phone application will open up a mini-browser and attempt to navigate to the specified uri on the web.  For instance, if the NavigateUri above is set to “bing.com”, the mini-browser will come up on the phone and display the following page:

minibrowser

2. Like the Silverlight Button control, HyperlinkButton uses the Content property to set the text for the hyperlink.  Like the Silverlight Button control, anything can be set to the Content.  This means we can use a trick familiar from web development to make an hyperlink look like something else – for instance, an image.

You can create a hyperlink like this:

hyperlink

simply by stacking some controls inside the content of your HyperlinkButton like so:

<HyperlinkButton Name="hyperlinkButton1"  
                    NavigateUri="/MyView.xaml" >
    <Border BorderBrush="White"
            BorderThickness="5"
            Padding="10">
    <StackPanel Orientation="Horizontal">
    <Image Width="60" 
            Source="/phoneapp1;component/Images/appbar.next.rest.png" />
        <TextBlock VerticalAlignment="Center" 
        Text="Go to View.xaml"></TextBlock>
    </StackPanel>
    </Border>
</HyperlinkButton>

3. You can also programmatically navigate between pages.  If your navigation is in the code-behind for a PhoneApplicationPage, you can take advantage of the NavigationService property of your page – which happens to return a System.Windows.Navigation.NavigationService instance.  This service will not only navigate to a page you specify, but will also maintain a history of pages visited in case the end-user decides to use the Windows Phone back button.

 

    this.NavigationService.Navigate(
        new System.Uri(
            "/MyView.xaml"
            ,System.UriKind.RelativeOrAbsolute)
            );

4.  If your navigation code needs to be placed somewhere other than in the code-behind for a PhoneApplicationPage – for instance in a UserControl – things become slightly more complicated.  In this case, the navigation service can be accessed through the PhoneApplicationFrame, which is the root visual for Windows Phone 7 applications.  The Frame has a Navigate method that calls the same NavigationService object we grabbed previously through the page.  The following example accesses the Frame’s navigation method from a Command on a ViewModel.

private void GoToMyView()
{
    var root = App.Current.RootVisual
        as PhoneApplicationFrame;
    root.Navigate(
        new System.Uri("/MyView.xaml"
        ,System.UriKind.RelativeOrAbsolute)
        );
}
private ICommand _navigationCommand;
public ICommand NavigationCommand{
    get
    {
        if (null == _navigationCommand)
        {
            _navigationCommand = new RelayCommand(GoToMyView);
        }
        return _navigationCommand;
    }
}

5. You can finally just change the source property on the PhoneApplicationFrame in order to navigate to a new page.  This is functionally equivalent to calling the Frame.Navigate method – in fact, changing the source property throws an event that ultimately calls the Frame.Navigate method.  The above code can be rewritten to this functionally equivalent code:

var root = App.Current.RootVisual
    as PhoneApplicationFrame;
root.Source =
    new System.Uri("/MyView.xaml"
    ,System.UriKind.RelativeOrAbsolute);