Windows 10 Development: Maintaining Application State

By August 10, 2015Windows
Windows-10-Hub-App-Template

We have so far created a simple app with two pages, that uses simple Frame navigation to go back and forth. However, the app is still missing one crucial feature: state management. When an app is suspended for whatever reason (such as being minimized on the desktop or navigated away from on the phone), it is up to the developer to maintain the current state so that it can be fully restored where the user left off.

In this post we’ll look at a simple way we can achieve this by leveraging helper classes from the Windows 8.1 project templates.

Template 10

It’s worth mentioning that there is a project called Template10 from the Windows XAML team that also addresses these issues, and is discussed in more detail in the MVA course A Developer’s Guide to Windows 10. I encourage you to explore that project as an alternative if you are looking for a more full-featured framework for Windows 10. For now, this post provides a quick-and-simple way to add state management to your app by recycling a few helper classes from Windows 8.1.

Windows 8.1 Universal App Hub Template

One of the more helpful components of the Windows 8.1 Universal SDK was the Hub App Template. It included several pages, controls and layouts demonstrating a functioning app complete with navigation. However, it also included a few base components to facilitate things like maintaining the navigation and application state.

Windows-10-Hub-App-Template

We’ll be leveraging the MvvmLight framework for navigation in a future post, but we can still leverage the SuspensionManager class from the template to make it easier to manage the state of a Windows 10 app.

Suspension Manager (Windows 8.1)

The SuspensionManager class from the 8.1 project can be used as-is, straight from the 8.1 template. Here’s a copy of the class that you can add to any project.

To leverage it, the app needs to do three things. First, the SuspensionManager needs to register the main frame of the application, which is done in the OnLaunched event. If necessary, the manager should also restore the previous state:

Next, the SuspensionManager needs to store the state when the app actually suspends, which occurs conveniently enough in the OnSuspended event. Note that since the operation is asynchronous, we need to first get then complete the suspension deferral:

The application is now configured to store and load state at the application level. However, the last step is to configure each view to also save and load the state of individual pages.

The 8.1 Universal Hub App does this through the NavigationHelper class, which we could certainly reuse in our app. However, MvvmLight already includes a NavigationService, which we’ll explore in our next post. Instead, we want to extract all the relevant code from the helper and wire it directly to the page itself.

ViewBase

Since we need this to execute on every page load (and unload), we’ll put this in a new ViewBase base class, from which all our pages will now derive. This allows us to override the OnNavigatedTo and OnNavigatedFrom events of every View to ensure that both the individual page state, as well as the complete navigation history, is serialized and saved so it can be reloaded for the user.

ViewModel State Events

There is one more advantage to this approach. Recall that the DataContext every page is now bound directly to its ViewModel, each of which derives from the same ViewModelBase class. By adding public Load and Save events to this class, we can fire them automatically from the page by adding a reference to this base ViewModel in our ViewBase and calling the events at the appropriate time.

Here is the modified ViewModelBase class with virtual events to Load and Save State. Each ViewModel will override these method (if needed) to load and save the state of their associated page.

Note that this also has an additional generic helper method RestoreStateItem to make it easy restore individual properties from the state; we’ll see this in action shortly.

Since we’re passing the state object to the ViewModel, we can add to it to save properties for later use if the application is suspended and restarted. For example, here we’ve added a simple text property to the SecondPage ViewModel, saving and loading its value from the state as the view is unloaded and loaded again.

Calling ViewModel Events from the Page

As previously mentioned, we want to fire the LoadState and SaveState events from the view automatically, which we can do by adding a reference to the ViewModel, which again is automatically stored in the DataContext.

Once we have that reference, we can wire into the LoadState and SaveState of the ViewBase class, pushing the event right through the pipeline.

Now all that is left is to add the code pulled from the original Windows 8.1 NavigationHelper class related to saving navigation state, and we have a complete system to manage both the application and navigation state.

Here is the complete ViewBase code:

The last step is to simply update all our views to inherit from this base class:

Note that since pages are partial classes you need to make sure that both the XAML and the code behind inherit from ViewBase:

Now we can remove the code from the code-behind related to state management so that it is fully driven by the LoadState and SaveState methods in each individual ViewModel. Best of all, since these events only fire during actual navigation, our Design Time data still remains available in both Visual Studio and Blend.

And of course, if we now run the app, navigate to the second page and enter some text, we can use the Visual Studio Lifecycle events menu to suspend the app:

Windows-10-App-Lifecycle-Events

Then launch the app again to verify that not only is our navigation state fully restored, but our TextBox content was also preserved:

Windows-10-Saving-applicaion-state

Generics in XAML

Since each ViewModel derives from a specific type, and we have a generic base class from which all our pages will derive, you might be tempted to define ViewBase as a generic <T> where T inherits from ViewModelBase. Unfortunately, although XAML does appear to have support for generics, this support does not yet appear to extend to Windows Store apps, so you must leave the reference to the ViewModel in the page DataContext as the base version.

However, if you do need to add a reference to your ViewModel in the code-behind, you can easily add a ViewModel property to the page, and cast the base to the appropriate type:

That way the ViewBase can still call all the state management events automatically underneath the covers, but at the individual page level, you can have a strongly-typed reference to the specific ViewModel associated with the page.

Wrapping Up and Next Steps

We now have a complete system that allows a Windows 10 application to manage navigation and application state, as well as an intuitive mapping of ViewModels to Pages including design time data to aid in laying out the application.

You can grab the complete project and follow along with the code by filling out this form here:

Get the CODE!

However, we have one more step to complete this framework, which is to leverage the NavigationService in MvvmLight to facilitate the navigation between pages. We’ll see how to achieve this, including supporting use of the ViewModels in other platforms in our next post.

The following two tabs change content below.