WP8 App/Page Base Navigation Classes

Posted by a Dev Theologian Tuesday, October 15, 2013 3:22:18 PM Categories: WP7 WP8

On my utilities page, I need to document a few of the items. The next one up is my App/Page Base Classes which you can get here at it’s repository.

Background

I created this set of classes in response to a DVLUP challenge criteria (Fast App Switching). The main reason I created these was because I wanted to be able to easily handle the various types of navigation to my pages with minimal thinking on my part. With Fast App Switching, you detect that via the Application_Activated event in the application (it gets passed to you via an event argument object). For me the best solution was to indicate this via a property on the application, and then I needed to remember to clear that property once I had responded to it. This last part was what spawned the new mechanism. Essentially, I split the page’s OnNavigatedTo method into 3 separate methods (that need to be overridden in child pages). The 3 methods are:

  • OnNormalNavigatedTo – a normal page-to-page navigation (or app launch) where you need to do an initial load of data
  • OnResumedFromTombstone – indicates that the page is being launched after a tombstoning situation (where you need to reload the page’s state
  • OnFastSwitchedTo – indicates that the page is being launched after returning from the OS, but nothing needs to be reloaded

All of these methods are passed a single argument of type: NavigationEventArgs which is the normal argument passed to the OnNavigatedTo Event. You can of course override the OnNavigatedTo event (and remember to call base.OnNavigatedTo(e) so that the new overrides get called.

Installation

There is a bit of work to wire all this up. First of all you need to grab the 2 new class files and drop them into your project. Next go ahead and compile the project (BTW, these classes MAY also work in WP7 projects). Now you need to wire up the application class. You need to do 2 things.

Set the App.xaml.cs class to inherit from DTNet.StateAwareApplication instead of Application. That will look something like this:

namespace MyProject
{
    public partial class App : DTNet.StateAwareApplication
    {


Additionally, you need to change the Application_Activated override method a little. It should look like this

        protected override void Application_Activated(object sender, ActivatedEventArgs e)
        {
            base.Application_Activated(sender, e);
            // Add any additional code you need in this event here
        }


Next you need to modify the app.xaml file by changing the base class. You probably have something that looks like this:

<Application
    x:Class="ProximityToy.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
 
    <!--Application Resources-->
    <Application.Resources>
        <local:LocalizedStrings xmlns:local="clr-namespace:ProximityToy" x:Key="LocalizedStrings"/>
    </Application.Resources>
 
    <Application.ApplicationLifetimeObjects>
        <!--Required object that handles lifetime events for the application-->
        <shell:PhoneApplicationService
            Launching="Application_Launching" Closing="Application_Closing"
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>
 
</Application>

 

You will need to add the DTNet namespace and change the “<Application” (or “</Application”)  to “<dtnet:StateAwareApplication “ (or “</dtnet:StateAwareApplication”). To convert the above xaml it would look like this:

<dtnet:StateAwareApplication 
    x:Class="ProximityToy.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:dtnet="clr-namespace:DTNet">
 
    <!--Application Resources-->
    <dtnet:StateAwareApplication.Resources>
        <local:LocalizedStrings xmlns:local="clr-namespace:ProximityToy" x:Key="LocalizedStrings"/>
    </dtnet:StateAwareApplication.Resources>
 
    <dtnet:StateAwareApplication.ApplicationLifetimeObjects>
        <!--Required object that handles lifetime events for the application-->
        <shell:PhoneApplicationService
            Launching="Application_Launching" Closing="Application_Closing"
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </dtnet:StateAwareApplication.ApplicationLifetimeObjects>
 
</dtnet:StateAwareApplication>

See how event the resources change. This is all that needs to be done to the application file.

You need to make similar changes for every page. Here’s a sample Xaml page that (with nothing in it):

<phone:PhoneApplicationPage
    x:Class="ProximityToy.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
    </Grid>    
</phone:PhoneApplicationPage>

We need to make this page reference the base class of the DTNet.StateAwareNavigationPage. We’ll do this just like we did for the App.xaml by adding the namespace reference and changing every occurrence of “<phone:PhoneApplicationPage” or “</phone:PhoneApplicationPage” to “<dtnet:StateAwareNavigationPage” or “</dtnet:StateAwareNavigationPage.” Here’s the xaml from above fixed:

<dtnet:StateAwareNavigationPage
    x:Class="ProximityToy.MainPage"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
    mc:Ignorable="d"    
    FontFamily="{StaticResource PhoneFontFamilyNormal}"    
    FontSize="{StaticResource PhoneFontSizeNormal}"    
    Foreground="{StaticResource PhoneForegroundBrush}"    
    SupportedOrientations="Portrait" Orientation="Portrait"    
    shell:SystemTray.IsVisible="True"
    xmlns:dtnet="clr-namespace:DTNet" >     
    
    <!--LayoutRoot is the root grid where all page content is placed-->    
    <Grid x:Name="LayoutRoot" Background="Transparent">    
    </Grid>    
</dtnet:StateAwareNavigationPage>

(the above example only had 2 text changes plus the namespace reference, but if you may have more references to “phone:PhoneApplicationPage” you will have to change them, so be aware).

Next you make the codebehind’s (aka PAGE.xaml.cs file) class derive from DTNet.StateAwareNavigationPage. This is pretty easy. You’ll also want to add the 3 new method overrides. It will look something like this:

// Using above this line
namespace MyProject
{
    public partial class MainPage:DTNet.StateAwareNavigationPage     
    {
        protected override void OnFastSwitchedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
        }
 
        protected override void OnResumedFromTombstone(System.Windows.Navigation.NavigationEventArgs e)
        {
        }
 
        protected override void OnNormalNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
        }
        
        // more code follows

 

Finally you will want to take the OnNavigatedTo Event (in your code) and remove the code placing it into the appropriate methods (you will probably create a method with the common code to reduce duplication of code). Finally delete the OnNavigatedTo Event (or at the least add a line that routine to call the base.OnNavigatedTo routine).

Just in case you missed this point, you do the page changes to every page you want to enable this functionality in.

Admittedly it is a lot of work for an existing project, but for a new one it’s not that bad. I have been meaning to create templates for this, but have never really had the time. Anyway, that’s it. Let me know what you think…

Just a reminder the 2 classes can be found on project’s repository.

Gravatar

Comments

Comments are closed on this post.
Site Map | Printable View | © 2008 - 2014 Intradynamics | Powered by mojoPortal | HTML 5 | CSS | Design by mitchinson