Simple No-Code Navigation in Windows Phone 7 Apps

Filed under Windows Phone 7

imageIn working with Windows Phone 7, one element that struck me as odd early on, is that the ApplicationBarIconButton (those “soft” buttons at the bottom of a normal WinPhone 7 page, highlighted in red in the screenshot) requires code in order to navigate. In other words, you MUST supply a CLICK event handler and in code behind, make use of the page’s NavigationService to perform the navigation.

Further, the URI to navigate to ends up in code behind as well.

Not ideal.

But there is a simple solution.

URIMapping

First, to make things really simple, you need to setup URI mapping. This allows your xaml to reference, say /Settings, and actually navigate to the URI /ui/SettingsPage.xaml?pvt=Main.

To do this, open up your App.xaml file and add something like this:

    <Application.Resources>
        <!-- URIs for navigation purposes -->
        <nav:UriMapper x:Key="UriMapper">
            <nav:UriMapping MappedUri="/ui/SettingsPage.xaml?pvt=Main" Uri="/Settings" />
        </nav:UriMapper>
    </Application.Resources>

Obviously, the MappedUri property is what you would normally use in conjunction with NavigationService.Navigate to actually perform the navigation. The Uri property is the new “simplified” Uri that you can use throughout your app to refer to the same page.

If you don’t already have it in your App.xaml file, be sure and add the namespace line for nav:

    xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone"

Create the New ApplicationBarIconNavigator control

Create a new class, call it ApplicationBarIconNavigator, and use the following code:

''' <summary>
''' Provides a handy extension to the ApplicationBarIconButton to facilitate direct navigation
''' </summary>
''' <remarks></remarks>
Public Class ApplicationBarIconNavigator
    Inherits ApplicationBarIconButton


    Public Property URI As Uri
        Get
            Return _Uri
        End Get
        Set(value As Uri)
            _Uri = value
        End Set
    End Property
    Private _Uri As Uri


    Private Sub ApplicationBarIconNavigator_Click(sender As Object, e As System.EventArgs) Handles MyBase.Click
        DirectCast(App.Current.RootVisual, PhoneApplicationFrame).Navigate(Me.URI)
    End Sub
End Class

This Class inherits from the normal ApplicationBarIconButton, but makes two critical changes.

First, it exposes a URI property, to allow us to specify what URI we want to navigate to.

Second, it automatically handles the Click event, and navigates to that URI.

This combination allows us to specify the URI to navigate to and handle the navigation event, all from XAML with no code on the page’s code behind at all.

The ApplicationBarDefinition

Now, in your page’s xaml, usually toward the end of the file is the definition of the ApplicationBar.

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBarIconButton IconUri="/Images/Settings.png" Text="Settings" Click="Settings_Click"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

Note that I’ve got only one button defined, and its Click event is set to About_Click, so normally, I’d have to navigate to the event handler, and add code there to perform the actual navigation:

    Private Sub Settings_Click(ByVal sender As Object, ByVal e As EventArgs)
        Me.NavigationService.Navigate(New Uri("/ui/SettingsPage.xaml?pvt=Main", UriKind.Relative))
    End Sub

Not a huge issue, but it does mean you’ve got code behind where there really doesn’t need to be any, which means more code to maintain, etc.

But, with the new control in place (you may have to perform a Build before you can add a reference on the page to it without error), and with the URIMappings set up, you can now do something like this:

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <local:ApplicationBarIconNavigator 
IconUri="/Images/Settings.png"
Text="Settings"
Uri="/Settings" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

At this point, you’re done! You no longer need the event handler logic because the ApplicationBarIconNavigator button will automatically handle it. And your URI complexity is isolated to just the App.xaml resources. Sweet!

One final note, if you haven’t already included one, you’ll need to add a “local” namespace declaration in your page’s xaml so that local:ApplicationBarIconNavigator will resolve.

    xmlns:local="clr-namespace:{your project name}" 

Wrapup

With MVVM frameworks like Prism, I believe this kind of functionality is baked in to some degree. But in my case, just starting out with WP7, I believe it’s important to understand the underpinnings of the system first, then progress to a higher level framework.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*