Windows Phone 7 - How to always launch your app where the user left off

30 September 2010

By default, there is no built in way in WP7 to ensure that your user is always navigated to the page they were last viewing when they used an application.

There are two sides to this problem. One is ensuring that for every page view, that the details of the page are persisted permanently in isolated storage so that regardless of how your app shuts down, the last viewed page details will be available.

The second side is how to dynamically navigate the user to this page on start up.

If you are using an MVVM framework such as Caliburn Micro (and you should), the first part is relatively trivial. FOr all your view models, ensure they inherit from a base class which in turns inherits from one of the core Caliburn Micro classes, in this case Screen.

The main thing is to ensure that you grab the View associated with the VM, cast to a PhoneApplicationPage and save the CurrentSource Uri value to isolated storage. Yes, VMs aren’t supposed to know about Views and all that, but I find it acceptable in this context. You can of course choose to do all this in the code behind of your View (As an aside I probably would do this if I could work out how to get a base View class working in WP7, still waiting on that one!).

public class AppViewModelBase : Screen
{
public override void AttachView(object view, object context)
{
var pageView = view as PhoneApplicationPage;
if (IsolatedStorageSettings.ApplicationSettings.Contains("LastViewedUri))
{
     IsolatedStorageSettings.ApplicationSettings["LastViewedUri"] = value;
}
else
{
     IsolatedStorageSettings.ApplicationSettings.Add("LastViewedUri", value);
}
}

We now need to perform the dynamic navigation when the app starts. One way to do this is to have a dummy page defined in your WMAppManifes.xml file such as ‘/RootPage.xaml’ which doesn’t actually exist.

Then you can handle the navigation event for the RootFrame (either in our Caliburn Micro bootstrapper or App.xaml.cs) and ensure that we test for the existence of the last viewed page value. If it’s not there, then we default the user to some other page (you can also check whether the user is logged in etc.). The advantage of this approach is that no page is put onto the back stack until your logic is run, so if the user hits back when they enter into the first page of your app, they exit the application which is nice and clean.

  void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            // Only care about RootPage (first time only) 
            if (e.Uri.ToString().Contains("/RootPage.xaml") != true)
                return;

            e.Cancel = true;

            RootFrame.Dispatcher.BeginInvoke(delegate
            {
                // check for last viewed page
                if (IsolatedStorageSettings.ApplicationSettings.Contains("LastViewedUri))
                {
                    RootFrame.Navigate(new Uri(IsolatedStorageSettings.ApplicationSettings["LastViewedUri"], UriKind.Relative));
                }
                else // specify default page here
                {
                    RootFrame.Navigate(new Uri("/Views/MainPageView.xaml", UriKind.Relative));
                }
            });
        }
Want to get started?

We would love to help with your next app or game, please do get in touch.