Home > C#, WinRT > A Base Page class for Windows 8.1 Store apps with C# and XAML

A Base Page class for Windows 8.1 Store apps with C# and XAML

10/10/2013

Project templates that ship with Visual Studio 2013 have been greatly modified compared to those of the 2012 version. Among all the other changes, the LayoutAwarePage class is no longer provided. In fact, visual states management based on the ApplicationViewState is deprecated on Windows 8.1.

However, LayoutAwarePage included some other important features, like Navigation support and Process lifetime management. So, in Visual Studio 2013 projects a new class is included, called NavigationHelper. As we can read in the comments of the source code:

[It] aids in navigation between pages. It provides commands used to navigate back and forward as well as registers for standard mouse and keyboard shortcuts used to go back and forward. In addition it integrates SuspensionManger to handle process lifetime management and state management when navigating between pages.

This class is automatically added to the solution if we use the Hub App, Grid App, and Split App project template or add to an existing project a BasicPage or any other Page item template other than BlankPage.

However, in the RC version of these templates, hasn’t been included a base page class that provides access to NavigationHelper functionalities. So, every page need to have a property of NavigationHelper type, that is instantiated in the constructor along with the registration of the events it raises.

This approach easily brings to a lot of repetitive code, that we know must be avoided whenever is possible. So, let’s see how to create a custom base page that we can use in our apps. Suppose we have added a BasicPage to the project. First of all, we need to remove all the references to NavigationHelper and ObservableDictionary classes from the code-behind file. Then, let’s define a new class named BasicPage:

public class BasicPage : Page
{
    private NavigationHelper navigationHelper;
    private ObservableDictionary defaultViewModel = new ObservableDictionary();

    public ObservableDictionary DefaultViewModel
    {
        get { return this.defaultViewModel; }
    }

    public NavigationHelper NavigationHelper
    {
        get { return this.navigationHelper; }
    }

    public BasicPage()
    {
        this.navigationHelper = new NavigationHelper(this);
        this.navigationHelper.LoadState += navigationHelper_LoadState;
        this.navigationHelper.SaveState += navigationHelper_SaveState;
    }

    private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
    {
        LoadState(e);
    }

    private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
    {
        SaveState(e);
    }

    protected virtual void LoadState(LoadStateEventArgs e) { }
    protected virtual void SaveState(SaveStateEventArgs e) { }

    #region NavigationHelper registration

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        navigationHelper.OnNavigatedTo(e);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        navigationHelper.OnNavigatedFrom(e);
    }

    #endregion
}

Now, we need to change the page XAML declaration to use the new base page. So, if we have created the BasicPage class in the Common namespace, the page tag must look like the following:

<common:BasicPage
    x:Name="pageRoot"
    x:Class="App1.MainPage"
    xmlns:common="using:App1.Common"
    ...>
    
</common:BasicPage>

The last step is to change the MainPage class declaration accordingly:

public sealed partial class MainPage : BasicPage

In this way, it isn’t necessary to declare the NavigationHelper in our pages anymore and, if we want to handle the LoadState and SaveState event (like in Visual Studio 2012 projects), we just need to ovverride the corresponding virtual methods:

protected override void LoadState(LoadStateEventArgs e)
{
    // Retrieves navigation parameters (if any).
    var parameters = e.NavigationParameter;

    // Restores session data (if any).
    if (e.PageState != null)
    {
        // ...
    }

    base.LoadState(e);
}

protected override void SaveState(SaveStateEventArgs e)
{
    // Saves Page session data.
    e.PageState.Add("Key1", "Value1");
    e.PageState.Add("Key2", "Value2");

    base.SaveState(e);
}

If you want more information about the navigation model in Windows Store apps, as usual you can refer to MSDN documentation.

Categories: C#, WinRT
%d bloggers like this: