Back-Chaining in WP7

Customizing App.xaml.cs

The Windows Phone 7 navigation system has certain limitations from a development perspective.  Chief among these are an inability to inspect the navigation backstack, an inability to remove items from the backstack, and an inability to navigate multiple pages on the backstack.

Because we are only able to programmatically back-navigate one page at a time, a technique has been devised in the developer community called back-chaining.  Back-chaining simply involves setting certain flags in your pages so that, if anyone ever backs into the page, it will continue to navigate backwards.  In this way, we can chain several back navigations together until we arrive at the page we want to stop at.

Here is a basic implementation that forces any back-navigation to always return to the first page in an application when this code is placed in every PhoneApplicationPage:

bool done;

protected override void OnNavigatedTo(
        NavigationEventArgs e)
{
    if (done && NavigationService.CanGoBack)
        NavigationService.GoBack();
}

protected override void OnNavigatedFrom(
    System.Windows.Navigation.NavigationEventArgs e)
{
    done = true;
}

Instead of repeating this code in every page, however, we can centralize it in the App class.  Additionally, we can provide extra methods for more complex navigation such as going back a certain number of pages or going back to a particular page wherever it is on the backstack.

We can do all of this from the App class because of an event on the PhoneApplicationFrame called Navigated that allows us to centrally hook into every navigation event in our applications.

In the default Windows Phone Application template, the PhoneApplicationFrame is instantiated in the App.InitializePhoneApplication method in the App.xaml.cs file.  We can declare our new handler for the event somewhere in there:

//boilerplate code
RootFrame.Navigated += CompleteInitializePhoneApplication;
//new code
RootFrame.Navigated += RootFrame_Navigated;

Next, we need to create some infrastructure code.  For convenience, we want to use static methods and properties in order to make our methods accessible off of the App class.  App.Current, which can be called from anywhere in your application, will return an Application type, which is the base class for App.  Consequently, to access the App class’s RootFrame property (which is boilerplate if you use one of the default project templates), you have to write code like this:

var rootFrame = ((App)App.Current).RootFrame;

A static member of the App class, on the other hand, can conveniently be called like this:

App.DoSomething();

Because we are spreading logic between several page navigations and consequently several calls to RootFrame_Navigated, our infrastructure will need to keep track of what we are trying to accomplish between all of these navigations.

The current implementation will include five methods for back navigation, a simple GoBack, GoBack for a number of pages, GoBack to a named page, GoBack to the first page, and GoBack past the first page.  The last is equivalent to exiting the application (it also doesn’t work, by the way, and I’ll talk more about that later).

Here is the implementation for the first back navigation — which is simply a standard one page back navigation placed in a more convenient place – as well as a property to expose CanGoBack:

public static void GoBack(string pageName)
{
    CurrentMode = GoBackMode.BackToPage;
    BackPageStop = pageName;
    GoBack();
}

private static bool CanGoBack
{
    get
    {
        var navFrame = App.Current.RootVisual
            as PhoneApplicationFrame;
        return navFrame.CanGoBack;
    }
}

GoBack can now be called from anywhere in a Silverlight application like this:

App.GoBack();

Our infrastructure code also requires an enum to keep track of these navigation types:

private enum GoBackMode
{
    Default = 0,
    BackNumberOfPages,
    BackToPage,
    Home,
    Quit
}

private static GoBackMode CurrentMode 
{ get; set; }

To implement going back a given number of pages, we will create a static property to track how many pages we need to go back and expose a method to start the GoBack chain:

private static int GoBackPageCount
{ get; set;}

public static void GoBack(int numberOfPages)
{
    CurrentMode = GoBackMode.BackNumberOfPages;
    GoBackPageCount = numberOfPages;
    GoBack();
}

The magic is what happens in the RootFrame_Navigated method, which is triggered every time we arrive at a new page in the application.  We check to see how many pages we have traversed through the backstack.  If we have gone far enough, we stop.  If not, we call App.GoBack():

static void RootFrame_Navigated(object sender
    , NavigationEventArgs e)
{
    switch (CurrentMode)
    {
        case GoBackMode.BackNumberOfPages:
            if (CanGoBack && --GoBackPageCount > 0)
            {
                GoBack();
            }
            else
                CurrentMode = GoBackMode.Default;
            break;

The setup code for going back to a named page tracks the targeted page name rather than the number of pages traversed:

private static string BackPageStop
{ get; set;}
public static void GoBack(string pageName)
{
    CurrentMode = GoBackMode.BackToPage;
    BackPageStop = pageName;
    GoBack();
}

The code fragment in the switch statement in RootFrame_Navigated parses the name of the page we have arrived at (e.Content returns the full class name along with its namespace but does not return the “.xaml” extension) and then compares it against the page we are trying to reach:

case GoBackMode.BackToPage:
    var pageName = e.Content.ToString();
    var periodPosition = pageName.LastIndexOf(".");
    if (periodPosition > -1)
        pageName = pageName.Substring(periodPosition + 1);
    if (CanGoBack && pageName != BackPageStop)
        GoBack();
    else
        CurrentMode = GoBackMode.Default;
    break;

The syntax for returning to MyPhoneApplication.Page1.xaml looks like this:

    App.GoBack("Page1");

If there are multiple instances of Page1 on the backstack, this implementation will stop at the last one.  If Page1 does not exist on the backstack, the routine will not stop until it finds the first page of the application.

GoHome is fairly straightforward.  It continues stepping backwards until the CanGoBack property returns false.  CanGoBack returns false on the first page of the application but returns true for every other page:

public static void GoHome()
{
    CurrentMode = GoBackMode.Home;
    GoBack();
}
    case GoBackMode.Home:
        if (CanGoBack)
            GoBack();
        else
            CurrentMode = GoBackMode.Default;
        break;

Finally, it would be really nice to be able to implement a Quit method.  Hypothetically, we could just navigate past the first page of an application to exit.  Taking advantage of the infrastructure we have written, the code would look like this:

public static void Quit()
{
    CurrentMode = GoBackMode.Quit;
    GoBack();
}
    case GoBackMode.Quit:
        GoBack();
        break;

Sadly, however, this doesn’t work. We cannot programmatically back navigate past the first page of an application.  When we try, the navigation is automatically cancelled and a NavigationFailed error is thrown. 

Since back-chaining as an exit strategy does not work, an alternative way to exit a Silverlight application is outlined here: How to Quit a WP7 Silverlight Application .  Unfortunately, the marketplace guidelines say that an application cannot have unhandled exceptions.  I’m not currently clear on whether this would apply to throwing an exception that is understood an controlled (hence handled) but at the same time intentional.

A word of caution:  Back-chaining causes flickering, and the more pages you navigate through, the worse the flickering gets.  This is because every page tries to display itself as you navigate past it.   A quick fix for the flickering problem is to set the RootFrame’s Opacity property to zero when you begin and complex back navigation and then set it back to one when you complete the navigation [thanks go to Richard Woo for pointing this out to me.]

For copy/paste convenience, here is the entire back-chaining code base:

RootFrame.Navigated += RootFrame_Navigated;
#region go back methods

private enum GoBackMode
{
    Default = 0,
    BackNumberOfPages,
    BackToPage,
    Home,
    Quit
}

private static GoBackMode CurrentMode 
{ get; set; }

public static void GoBack()
{
    var navFrame = App.Current.RootVisual
        as PhoneApplicationFrame;
    navFrame.GoBack();
}

private static void ShowRootFrame(bool show)
{
    var navFrame = App.Current.RootVisual
        as PhoneApplicationFrame;
    if (show)
        navFrame.Opacity = 1;
    else
        navFrame.Opacity = 0;
}

private static int GoBackPageCount
{ get; set;}

public static void GoBack(int numberOfPages)
{
    CurrentMode = GoBackMode.BackNumberOfPages;
    GoBackPageCount = numberOfPages;
    ShowRootFrame(false);
    GoBack();
}

private static string BackPageStop
{
    get;
    set;
}
public static void GoBack(string pageName)
{
    CurrentMode = GoBackMode.BackToPage;
    BackPageStop = pageName;
    ShowRootFrame(false);
    GoBack();
}

private static bool CanGoBack
{
    get
    {
        var navFrame = App.Current.RootVisual
            as PhoneApplicationFrame;
        return navFrame.CanGoBack;
    }
}

public static void GoHome()
{
    CurrentMode = GoBackMode.Home;
    ShowRootFrame(false);
    GoBack();
}

public static void Quit()
{
    CurrentMode = GoBackMode.Quit;
    ShowRootFrame(false);
    GoBack();
}

static void RootFrame_Navigated(object sender
    , NavigationEventArgs e)
{
switch (CurrentMode)
{
    case GoBackMode.BackNumberOfPages:
        if (--GoBackPageCount > 0 && CanGoBack)
        {
            GoBack();
        }
        else
        {
            ShowRootFrame(true);
            CurrentMode = GoBackMode.Default;
        }
        break;
    
    case GoBackMode.Home:
        if (CanGoBack)
            GoBack();
        else
        {
            ShowRootFrame(true);
            CurrentMode = GoBackMode.Default;
        }
    break;
    case GoBackMode.BackToPage:
        var pageName = e.Content.ToString();
        var periodPosition = pageName.LastIndexOf(".");
        if (periodPosition > -1)
            pageName = pageName.Substring(periodPosition + 1);
        if (CanGoBack && pageName != BackPageStop)
            GoBack();
        else
        {
            ShowRootFrame(true);
            CurrentMode = GoBackMode.Default;
        }
        break;
    case GoBackMode.Quit:
        GoBack();
        break;

    }
}

#endregion

20, 50, 90, 400 and 2

the-count

There are certain numbers every Windows Phone developer should be familiar with: 20, 50, 90, 400, and 2.

20 MB is the maximum size of a XAP file that can be downloaded over the air.  XAPs larger than this must use Wi-Fi or the Zune desktop app to be downloaded to a device.

50 MB is the maximum size of additional content that can be downloaded after installation to make the application functional.  If more than 50 MB is needed to make the application functional, this must be noted in the marketplace submission and a notification should be provided to the end-user of the fact.

90 MB is the memory usage limit for your app assuming the device has the min-spec 256 MB of RAM.  Of course, another way to look at this is that Windows Phone 7 reserves 166 MB of RAM for itself – your app can use the rest.  If the device has 512 MB of RAM, then your app gets 256 + 90.

400 MB is the max allowable size for your XAP. 

2 Gigs is the total size your app can grow to.  This includes the XAP as well as any data you throw into isolated storage — though some people have proposed that the 2 Gig limit applies only to isolated storage usage.  (If you check the isolated storage quota programmatically, it appears to be unlimited which, obviously, isn’t the case). 

The 2 Gig limit seems to have been lifted.  To read more about this, see the old MSDN forums.

Just another ViewModelBase class

Great developers like Laurent Bugnion, Rob Eisenberg and Rocky Lhotka write Frameworks.

At the opposite end of the spectrum are developers like me.  I write helper classes.  Usually I don’t even do that and simply resort to copy and pasting from text files I have saved all over my harddrive.

In the zip file you will find a ViewModel base class designed specifically for doing MVVM in a Windows Phone Silverlight application.  It can be used with either the Satellite VM pattern or the Anchor VM pattern as described in the Patterns of Windows Phone Architecture series.  It supports Blendability, State persistence, Tombstoning and Xaml-only instantiation.

Also included are the helper classes for saving state described in this post.

Basic usage looks like this:

public class MainViewModel: 
    SerializableViewModelBase<MainViewModel>{}

All the features mentioned above come free simply by inheriting the base class.  Add a property, rinse, repeat.

And here’s the implementation below.  The code in the base constructor takes the currently newed up instance and throws it into the static instance. 

You’ll also note that unlike a typical Singleton implementation, the instance property is not static.  This allows XAML instantiation to work properly.  A protected Singleton property is provided if you want the Instance property to be static in the derived class.  To implement a static Instance property in the derived class, just add one with the new qualifier like this:

public static new MainViewModel Instance
{
    get { return Singleton; }
}

BackupMore and RestoreMore can be overridden to save additional state data that might not get serialized with the ViewModel but belongs with it nonetheless (for instance, private fields that need to be saved off).

InitializeDesigner and InitializeInstance can be overriden to perform any initialization logic.  Since with XAML instantiation using a static Instance can create your object more than once, the base class is written so these two methods are only called on the first instantiation of the singleton.  Additionally, they automatically perform forking logic for instantiation code running in the designer versus instantiation code at runtime.

Your comments and advice are, as always, welcome.

public abstract class SerializableViewModelBase<T>
    : INotifyPropertyChanged
    where T : SerializableViewModelBase<T>, new()
{

    private static T _instance;
    private static object _lockObject = new object();

    /// <summary>
    /// Initializes a new instance of 
    /// the <see cref="SerializableViewModelBase&lt;T&gt;"/> 
    /// class.
    /// </summary>
    public SerializableViewModelBase()
    {
        lock (_lockObject)
        {
            if (IsInstanceEmpty)
            {
                _instance = (T)this;
                Initialize();
            }
        }
    }

    /// <summary>
    /// Gets a value indicating whether 
    /// the singleton instance T is empty.
    /// </summary>
    /// <value>
    ///     <c>true</c> if this instance is empty;
    ///     otherwise, <c>false</c>.
    /// </value>
    protected static bool IsInstanceEmpty
    {
        get { return _instance == null; }
    }

    /// <summary>
    /// Override to perform runtime intialization.
    /// </summary>
    virtual protected void InitializeInstance() { }
    /// <summary>
    /// Override to perform initialization for 
    /// the designer.
    /// </summary>
    virtual protected void InitializeDesigner() { }

    private void Initialize()
    {
        if (DesignerProperties.IsInDesignTool)
            InitializeDesigner();
        else
            InitializeInstance();
    }

    /// <summary>
    /// Gets the singleton instance of type T.
    /// </summary>
    /// <value>The instance.</value>
    protected static T Singleton
    {
        get
        {
            lock (_lockObject)
            {
                if (IsInstanceEmpty)
                    new T();
            }
            return _instance;
        }
    }

    /// <summary>
    /// Gets the singleton instance of type T.
    /// </summary>
    /// <value>The instance.</value>
    public T Instance
    {
        get
        {
            return Singleton;
        }
    }

    private string _title;
    /// <summary>
    /// Gets or sets the Title.
    /// </summary>
    /// <value>The title.</value>
    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged("Title");
        }
    }

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (null != PropertyChanged)
            PropertyChanged(this
            , new PropertyChangedEventArgs(propertyName));
    }

    /// <summary>
    /// Backs up the class instance.
    /// </summary>
    /// <param name="store">The data store.</param>
    /// <returns></returns>
    public static bool Backup(IDataStorage store)
    {
        _instance.BackupMore(store);
        return store.Backup(typeof(T).Name, _instance);
    }

    /// <summary>
    /// Restores the class instance.
    /// </summary>
    /// <param name="store">The data store.</param>
    public static void Restore(IDataStorage store)
    {
        _instance = store.Restore<T>(typeof(T).Name);
        _instance.RestoreMore(store);
    }

    /// <summary>
    /// Override this method to backup additional state.
    /// </summary>
    /// <param name="store">The store.</param>
    protected virtual void BackupMore(IDataStorage store) { }

    /// <summary>
    /// Override this method to restore additional state.
    /// </summary>
    /// <param name="store">The store.</param>
    protected virtual void RestoreMore(IDataStorage store) { }
}

Patterns of Windows Phone Architecture Part III

The Anchor ViewModel pattern described in part 2 of this series is especially well adapted to Hub style layouts where related user controls are organized under a common parent.  For instance, a Pivot Control can have a MainViewModel object assigned to its DataContext.  If the MainViewModel class has properties with additional ViewModels, for example DetailsName, DetailsAddress, and so on, each of these properties can be used as the DataContexts of the Pivot Items contained in it.

Here’s a simple illustration of what that would look like:

<controls:Pivot 
    DataContext="{Binding  
    Source={StaticResource MainVM}}" 
    Name="pivot1" Title="{Binding Title}" 
    >
    <controls:PivotItem 
        DataContext="{Binding DetailsName}"
        Header="{Binding Title}">
        <StackPanel >
            <TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
            <TextBox Text="{Binding LastName, Mode=TwoWay}" />
        </StackPanel>
    </controls:PivotItem>
</controls:Pivot>

Using the tip from Tombstoning Simplified, tombstoning your application only requires a single call in order to save to transient storage not only the MainViewModel but also all of its dependent ViewModels:

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    MainViewModel.Backup(new TransientDataStorage());
}

This pattern work less well if your phone application consists of unrelated pages with unrelated view models backing them. 

In order to maintain the one line tombstoning code, you can still have a RootViewModel that consists only of properties for each ViewModel in the application.  The RootViewModel can be assigned to the DataContext of the PhoneApplicationFrame of your application, and each subsequent page in the app can simply have its DataContext bound to the properties of the RootViewModel.

Practically speaking, this is an effective architecture.  It will accomplish everything you need in your app for tombstoning. 

On an aesthetic level, however, I find it displeasing to have unrelated ViewModels dependent on one another.  Additionally, having a super ViewModel, the purpose of which is only to host other ViewModels, makes my eye twitch.

In my own applications I use a different pattern called the Satellite ViewModel pattern.  It complements the Anchor ViewModel pattern and shouldn’t be considered opposed to it.  Each pattern ought to be used where it is most appropriate to do so.

3. Satellite ViewModel

Satellites orbit the earth without any awareness of each other.  Each can be communicated with independently of its fellow crafts.  Where the Anchor ViewModel pattern privileges one object above all others, satellites are all equal with respect to one another.

In order to implement the Satellite View Model Pattern for Windows Phone applications, we will simply take advantage of one of the oldest and best-known design patterns: The Singleton.  In order to make it play well in the Phone environment, however, we will give it a little twist.

The goals of this pattern are:

  1. to preserve state for a View (a PhoneApplicationPage or UserControl) even when the View is out of scope.
  2. to allow fine-grained access to Views as needed
  3. to support easy backup to transient or isolated storage if the application is tombstoned or simply terminated.
  4. to provide an MVVM architecture that is Blendable.

A ViewModel, at minimum, should of course implement INotifyPropertyChanged.  Here is the boiler-plate implementation most people use:

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (null != PropertyChanged)
            PropertyChanged(this
                , new PropertyChangedEventArgs(propertyName));
    }
}

To allow for general access to this ViewModel while preserving state no matter what happens to associated Views, we implement the singleton pattern:

protected static MainViewModel _instance;

private static object _lockObject = new object();
public static MainViewModel Instance
{
    get
    {
        lock (_lockObject)
        {
            if (_instance == null)
                _instance = new MainViewModel();
        }
        return _instance;
    }
}

So far this is pretty standard code.  We’ve even added a standard thread-safety measure with the lock keyword.

The Singleton Pattern (as well as the related Factory Method Pattern) typically implements a private no parameter constructor in order to prevent instantiation using the new() keyword.

We can’t do this for windows phone for two reasons.

First, both Isolated Storage and transient storage to the State object use XML serialization in a partial trust environment.  Consequently, if we want to backup our ViewModels to persistent or transient storage, our ViewModels must have public no param constructors.

Second, in order to make our ViewModels blendable, we also require public no param constructors since Silverlight for Phone does not support referencing static classes in XAML.  The constraints of the Silverlight environment on the phone force us down certain architectural paths and we are obligated to tweak some old tried-and-true patterns in order to create new ones.

In order to support both blendability and serialization, our MainViewModel’s constructor will look like this:

public MainViewModel(){}

It’s awkward, I grant you. 

With respect to serialization, we are required to have a public no param constructor even if it has no code in it.  Furthermore, when the ViewModel is deserialized, the constructor is never actually called (even though we were required to have it).  If you are using a base class for your ViewModels, as many people do, you must also provide a public no param constructor for your base class  (yes! even if it is marked as an abstract base class).

In order to instantiate our ViewModel in XAML and use it as our DataContext, we will add it to our class DataContext attribute using some special syntax. The XAML for assigning a MainViewModel instance to the page’s DataContext looks like this:

d:DataContext="{d:DesignInstance local:MainViewModel,
IsDesignTimeCreatable=True}" 

Instantiating the MainViewModel instance in XAML like this makes our VM blendable.  The point of making the MainViewModel blendable is to be able to visualize how the View and the ViewModel work together.  Additionally, you may want to show data when you are designing the application which you do not want to show when you are actually running the application.  You can handle this in the Constructor method (the one we originally didn’t want to have) for your VM like so:

    public MainViewModel()
    {
        if (DesignerProperties.IsInDesignTool)
        {
            Title = "Design Mode";
        }
        else
        {
            Title = "My Application";
        }
    }

The IsInDesignTool is the magic sauce that tells us whether we are running this code through a designer or in a live application.

On the XAML side, there is an additional chunk of XAML I haven’t shown you yet.  The code presented so far will allow you to instantiate and run code in the designer only.  In order to have VM code that runs in both the designer and at runtime, however, we will set the DataContext again.  This will look like we are duplicating code, but we aren’t really. 

The purpose of this code segment is simply to set the PhoneApplicationPage’s DataContext to the Instance property for the running application as well as the design-time application (for runtime purposes, of course, it isn’t necessary to perform binding in the xaml.  It could just as well be done programmatically in the Page’s constructor):

    <phone:PhoneApplicationPage 
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DataContext="{d:DataInstance local:MainViewModel,
    IsDesignTimeCreatable=True}" >
    <phone:PhoneApplicationPage.DataContext>
        <Binding Path="Instance">
            <Binding.Source>
                <local:MainViewModel/>
            </Binding.Source>
        </Binding>
    </phone:PhoneApplicationPage.DataContext>
    ...

Now to put in some code for tombstoning.  For this we just require two static methods, one for serializing the VM and one for rehydrating it.  Using the helper classes from here the serialize/deserialize code on MainViewModel looks like this:

private string token = "MainViewModel";

public static bool Backup(IDataStorage store)
{
    return store.Backup(token, _instance);
}

public static void Restore(IDataStorage store)
{
    _instance = store.Restore<MainViewModel>(token);
}

In the App class, we hook into the phone services events to call Backup and Restore for all of our VMs.  The code below assumes that we have three ViewModels we want to save off.  RestorePersistentData and BackupPersistentData are simply custom methods for saving to IsolatedStorage explained in this Tip

They are in this sample code simply to illustrate that any data you want to save off when the application permanently terminates should also be saved off when you prepare your app for tombstoning since there is no guarantee the application will be revived after tombstoning :

private void Application_Activated(object sender
    , ActivatedEventArgs e)
{
    RestorePersistentData();

    var store = new TransientDataStorage();
    TwitterDetailsViewModel.Restore(store);
    ContactsViewModel.Restore(store);
    MainViewModel.Restore(store);
}

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    var store = new TransientDataStorage();
    MainViewModel.Backup(store);
    ContactsViewModel.Backup(store);
    TwitterDetailsViewModel.Backup(store);

    BackupPersistentData();
}

private void Application_Launching(object sender
, LaunchingEventArgs e)
{
    RestorePersistentData();
}
       
private void Application_Closing(object sender
    , ClosingEventArgs e)
{
    BackupPersistentData();
}

To summarize, the Satellite ViewModel – which is really a somewhat deviant mixing of the Singleton pattern and the ViewModel pattern to make them work on the Phone – is intended to accomplish four goals:

  1. Support a stateful phone application architecture.
  2. Allow easy accessibility to ViewModels.
  3. Facilitate tombstoning scenarios.
  4. Provide a Blendable ViewModel pattern.

If you don’t like some of the jury-rigging required to make the above code work, I would highly recommend you look at Laurent Bugnion’s ViewModel Locator pattern: http://www.galasoft.ch/mvvm/getstarted/ .  As of this writing, the MVVM Light ViewModel base class doesn’t deserialize correctly because it doesn’t have a public no param constructor.  To work around this, you simply have to copy the BaseViewModel class into your own implementation and add a constructor.

[Note: this code was cleaned up on 10/17/10 to use the DataInstance extension for design time binding to the DataContext.  Many awkward issues regarding instantiation go away by using this syntax.]

WP7 Tip: tombstoning simplified

In order to prepare your phone app to go into tombstone mode (to make it tomb-worthy) it is necessary to save off state data associated with your app.  My preference is to simply save off view models – but you may want to also save off model objects or even individual field values.

There are two dictionaries for doing this. 

IsolatedStorageSettings.ApplicationSettings is available to save persistent data between runs of the application (whether the application gets tombstoned or simply gets closed down).

PhoneApplicationService.Current.State allows one to save and restore data when the application gets tombstoned.  It is handy if we only want to save off data temporarily – for instance if we do not need it for a fresh run of the application. 

Since State and ApplicationSettings are both dictionaries that automatically handle serialization and deserialization for us, much of the underlying code we are required to write when using them is also very similar.

In my own applications, I use a set of utility classes to ease saving and restoring my application state.

Since I generally only want to use State and ApplicationSettings to save and restore data, I encapsulate the plumbing behind a very simple interface.

    public interface IDataStorage
    {
        bool Backup(string token, object value);
        T Restore<T>(string token);
    }

The concrete classes aren’t particularly sophisticated.  I use this for transient data storage:

    public class TransientDataStorage: IDataStorage
    {

        public bool Backup(string token, object value)
        {
            if (null == value)
                return false;

            var store = PhoneApplicationService.Current.State;
            if (store.ContainsKey(token))
                store[token] = value;
            else
                store.Add(token, value);

            return true;
        }

        public T Restore<T>(string token)
        {
            var store = PhoneApplicationService.Current.State;
            if (!store.ContainsKey(token))
                return default(T);

            return (T) store[token];
        }
    }

And this for isolated storage:

    public class PersistentDataStorage: IDataStorage
    {

        public bool Backup(string token, object value)
        {
            if(null == value)
                return false;

            var store = IsolatedStorageSettings.ApplicationSettings;
            if (store.Contains(token))
                store[token] = value;
            else
                store.Add(token,value);

            store.Save();
            return true;
        }

        public T Restore<T>(string token)
        {
            var store = IsolatedStorageSettings.ApplicationSettings;
            if (!store.Contains(token))
                return default(T);

            return (T) store[token];
        }
    }

You’ll notice that the only real difference between these two code segments is that I need to call Save for isolated storage but do not have to for State updates.

Now when I need to save to isolated storage I simply call:

    var store = new PersistentDataStorage();  
    store.Backup("token", myObject);

While a transient save to State is simply:

    var store = new TransientDataStorage();  
    store.Backup("token", myObject);

No sticky kids mess afterwards.

I like having an interface as it allows me to throw some methods on the VMs themselves:

public static bool Backup(IDataStorage store)
{
    return store.Backup("MainViewModel", this._instance);
}

public static void Restore(IDataStorage store)
{
    this._instance = store.Restore<MainViewModel>("MainViewModel");
}

In this case, each VM is responsible for what actually gets saved to storage: for instance, we might want to save off the VM as well as the  associated model object. 

Whether this state is saved off to IsolatedStorage or State, however, gets determined elsewhere – generally in the ApplicationService lifecycle events: Launching, Closing, Activated and Deactivated.

WP7 Tombstoning Pattern Tip

Customizing App.xaml.cs

If you are familiar with tombstoning on Windows Phone, you know there are four events in the Windows Phone application lifecycle that can be handled: PhoneApplicationService.Launching, PhoneApplicationService.Closing, PhoneApplicationService.Activated and PhoneApplicationService.Deactivated.  The first two are for normal app startup and shutdown, while the latter two are for tombstoning scenarios.

Along with these events are two different property bags that application data can be saved to. 

IsolatedStorageSettings.ApplicationSettings  is typically used for backing up persistent data that you want available every time the application starts up. 

PhoneApplicationService.Current.State is used for transient data that you only want persisted if your Silverlight application gets tombstoned.  It is the equivalent of session data in an ASP.NET web application.

In the Launching and Closing event handlers you would typically save to Isolated Storage, while in handlers for Activated and Deactivated you would want to use Current.State.  The former coding artifacts are for persistent data while the latter are for transient data.

These categories are imperfect, however.  It is possible to go through the Deactivated event but never have Activated called.  This occurs if for memory management reasons your application is permanently terminated (a permanent death scenario rather than the temporary death that tombstoning is supposed to trigger).  This can also happen, of course, if the user for whatever reason just decides not to return to your app after it gets tombstoned.

Another way to look at this is that your application is permanently terminated without ever invoking the PhoneApplication.Closing event.

In order to handle this common scenario, you must save any persistent data in the Deactivated event as well as the Closing event.

A simple pattern for structuring your code to cover all these possibilities is to make sure the code fragment for saving persistent data is called in both the Dectivated and Closing event handlers.  Similarly, the fragment for restoring persistent data should be called in both the Activated and Launching handlers.  We do this by taking care of persistent data backup and restores in two new methods: BackupPersistentData and RestorePersistentData. Those who remember the IDisposible pattern in C# will recognize some of the same coding idioms being used here.

The following code goes in App.xaml.cs:

private void BackupPersistentData()
{
    var store = IsolatedStorageSettings.ApplicationSettings;
    //save persistent data
    store.Save();
}
private void RestorePersistentData()
{
    var store = IsolatedStorageSettings.ApplicationSettings;
    //restore persistent data
}

private void Application_Closing(object sender
    , ClosingEventArgs e)
{
    BackupPersistentData();
}

private void Application_Launching(object sender
    , LaunchingEventArgs e)
{
    RestorePersistentData();
}

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    BackupPersistentData();
    var store = PhoneApplicationService.Current.State;
    //save transient data
}

private void Application_Activated(object sender
    , ActivatedEventArgs e)
{
    RestorePersistentData();
    var store = PhoneApplicationService.Current.State;
    //restore transient data
}

Sticking to this pattern has helped me to avoid a lot of unforeseen mistakes in my own phone apps.

 



Getting the current theme in WP7 for Silverlight

Customizing App.xaml.cs

Windows Phone devices allow users two theme options, either dark or light.

In the WP7 beta dev tools, however, there no straight-forward way for Windows Phone Silverlight developers to find out what the current theme is, though there is a hack.  The developer must interrogate the app resources to find the color of the PhoneBackGroundColor.  Under the dark theme it is black, while under the light theme it is white.

The following code can be thrown into App.xaml.cs to add a little elegance to this hack. 

First, a brief enum is needed.  It can be added in App.xaml.cs above the App class, or simply placed in its own cs file in the project:

public enum Theme{Light,Dark}

A CurrentTheme property is added to the App class:

private static Theme _currentTheme;

public static Theme CurrentTheme
{
    get { return _currentTheme; }
    private set { _currentTheme = value; }
}

And then we assign a value to CurrentTheme in the App class constructor by interrogating Resources:

public App()
{
    var bgc = Resources["PhoneBackgroundColor"].ToString();
    if (bgc == "#FF000000")
        CurrentTheme = Theme.Dark;
    else
        CurrentTheme = Theme.Light;

    //etc.

The CurrentTheme is now retrievable from anywhere in the application like so:

    switch(App.CurrentTheme)
    {
        case Theme.Dark:
            MessageBox.Show("Dark");
            break;
        case Theme.Light:
            MessageBox.Show("Light");
            break;
    }

Moreover, if a user presses the Windows button at lower center on a device and resets the theme, the new theme will be assigned to CurrentTheme when the application returns from tombstoning.

There is a rumor that in the RTM of the WP7 dev tools, two new properties will be available for picking up the current theme: DarkThemeVisibility and LightThemeVisibility.

For ease of migration to the RTM, you can add the following two properties to App.xaml.cs for now as placeholders – you should be able to simply switch them out later should the new methods become available:

public static bool DarkThemeVisibility
{
    get { return CurrentTheme == Theme.Dark; }
}

public static bool LightThemeVisibility
{
    get { return CurrentTheme == Theme.Light; }
}

How to Quit a WP7 Silverlight Application

Customizing App.xaml.cs

In the current Beta dev tools for Windows Phone 7, there is no way to exit a Silverlight application (though there is a method to do this for XNA apps).

Currently the best way – and I use the term “best” loosely – to do this is to throw an exception.  An unhandled exception always manages to kill your application.

If we must use a hack, however, we might as well  do it with a bit of finesse.  Below is a simple implementation that can be placed in the App class of a WP7 Silverlight project that clarifies the behavior of the app when we intentionally throw an exception in order to exit rather than simply throwing an exception exceptionally.

This code can be called from anywhere in your app in order to Exit predictably.

Here is the call:
App.Quit();
And here is the implementation in App.xaml.cs:
private class QuitException : Exception { }

public static void Quit()
{
    throw new QuitException();
}

private void Application_UnhandledException(object sender, 
    ApplicationUnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is QuitException)
        return;

    if (System.Diagnostics.Debugger.IsAttached)
    {
        System.Diagnostics.Debugger.Break();
    }

    //etc.
}
Windows Phone 8 Update

If you are doing Windows Phone 8 development, things get easier.  After having so many apps going through the store using the above method to exit out, the WP Dev\Design team decided to just implement their own escape method.  Sometimes the doctor is right and sometimes the patient just has a better understanding of what the pain feels like.  To exit out of a Windows Phone 8 app, call Application.Terminate .

Patterns of Windows Phone Architecture Part II

When the WP7 beta dev tools were released, developers were pleased to find several new events hanging off of Shell.PhoneApplicationService for managing a phone application’s life cycle: Launching, Closing, Activated and Deactivated.  The first two events are obviously thrown when an application is first launched and when it is closed down (either by hitting the back button past the first page in the app or, interestingly, by throwing an unhandled exception).

The Activated and Deactivated events are thrown when the application is interrupted mid-run – typically by launching a Windows Phone task or by hitting the Windows button on the phone.  This is a scenario known as tombstoning.

If you are not yet familiar with the concept of tombstoning or simply need a refresher, please read Yochay Kiriaty’s post on the subject here.

These new events give Silverlight for WP7 developers a way to manage application state outside of the navigation events on each page.  Two design considerations must be taken into account, however, in order to take advantage of this centralized way of persisting state information.  1. All data that needs to be persisted between application runs or during tombstoning must be accessible from the event handlers for the four lifecycle events.  2. If application data persistence is handled outside of each page, another mechanism is required for persisting page state information as well as model data between page instantiations.

2. Anchor ViewModel

The Pledge

An anchored boat is able to stay in one place while currents wash away unmoored items floating on the ocean.  Anything tethered to the boat, or tethered to something tethered to the boat, is likewise stationary.  This is the main concept behind an Anchor ViewModel phone architecture.

While the developer has little control over the lifespan of a PhoneApplicationPage, he can nevertheless control the life of the state of the page if he is using an M-V-VM pattern.  There are several artifacts in the application that ViewModels can be tethered to and which survive the constant newing up and dereferencing of Views in a Silverlight app for the phone.  The Application itself can serve as an anchor.  It has a RootVisual, the PhoneApplicationFrame, which hosts (typically) a MainPage.xaml PhoneApplicationPage that doesn’t go out of scope until the application is terminated.  ViewModels can be tethered to any of these objects in order to give them a lifespan beyond the lifespan of their respective Views.

The Windows Phone Databound Application Template that is provided with Visual Studio for Windows Phone demonstrates this anchoring technique.  In this sample template, the MainViewModel object hangs off of the App class.  When the MainPage view is instantiated, the App’s MainViewModel instance is assigned to the MainPage view’s DataContext. At this point, the lifecycle of MainViewModel is tethered to the lifecycle of App rather than to the lifecycle of MainPage.

The DetailsPage view, in turn, retrieves its DataContext from a ViewModel hanging off of MainViewModel which hangs off of App.  The lifecycle of the ItemViewModel is tethered to the lifecycle of MainViewModel which in turn is anchored to the App class.

The Turn

This is more evident if we change the default application based on the Windows Phone Databound Application Template a little.  First, MainViewModel can be modified to include a SelectedItem property:

private ItemViewModel _selectedItem;
public ItemViewModel SelectedItem 
{
    get { return _selectedItem; }
    set 
    { 
        _selectedItem = value;
        NotifyPropertyChanged("SelectedItem");
    }
}

Then the ListBox in MainPage.xaml should have it’s SelectedItem attribute bound to this property:

<ListBox x:Name="MainListBox" 
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
            ItemsSource="{Binding Items}"

We simplify the MainListBox’s SelectionChanged event handler like so:

// Handle selection changed on ListBox
private void MainListBox_SelectionChanged(object sender
    , SelectionChangedEventArgs e)
{
    // If selected index is -1 (no selection) do nothing
    if (MainListBox.SelectedIndex == -1)
        return;

    // Navigate to the new page
    NavigationService.Navigate(new Uri("/DetailsPage.xaml"
        , UriKind.Relative));
}

Finally, in our details page, we would set the DataContext in the constructor rather than in the OnNavigatedTo method:

public DetailsPage()
{
    InitializeComponent();
    if (DataContext == null)
        DataContext = App.ViewModel.SelectedItem;
}

The point to remember here is that when the DetailsPage view goes out of scope through a back page navigation, the VM for DetailsPage continues to exist in memory and remains accessible because it is tethered to MainViewModel. 

More importantly, if we change a property on the ItemViewModel we are using for the DataContext of DetailsPage, these changes would be persisted back to MainViewModel after we navigate away from DetailsPage, and would remain persisted for as long as the current App is held in memory.

The Prestige

The payoff to this pattern is that we can now handle tombstoning by persisting all of our VMs centrally in a few lines of code:

string _appToken = "all_vms";

private void Application_Activated(object sender
    , ActivatedEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(_appToken))
        viewModel = store[_appToken] as MainViewModel;
}

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(_appToken))
        store[_appToken] = viewModel;
    else
        store.Add(_appToken, viewModel);
}

Because all view models are anchored to MainViewModel, saving our top level view model will also automatically serialize and later deserialize all the of VMs hanging off of MainViewModel as well as the state of their properties.

We have effectively made the entire default Databound Phone Application sample “tombworthy”.   If you now tombstone the application while navigated to the DetailsPage (for instance by pressing the Windows button at bottom center), it will be restored when you return to the application.

In an application with 5, 10 or more VMs, this will be very handy.

The next post in this series will cover the Satellite ViewModels pattern, which uses many of the same principles but allows greater control over how and what state gets persisted.

 

 

Patterns of Windows Phone Architecture Part 1

The Windows Phone platform introduces several problems for the software architect which, if not completely absent in standard Silverlight applications, are nevertheless more acute. The most important of these revolve around state: the state of data during the running of an application and the state of the data between runs.

Because Windows Phone design is structured around the phone navigation frame, a Silverlight out-of-browser application on the phone behaves more like a web application than a stateful application.  The lifespan of a typical PhoneApplicationPage is uncertain. 

While the first page in a Phone application’s backstack (usually MainPage.xaml) is tied to the lifespan of the application itself, all other pages are only accessible while currently displayed or existing in the backstack.  By existing on the backstack, I here mean accessible 1. by pressing the back button and 2. by calling NavigationService.GoBack() .

Once a page is no longer visible because a user has navigated back, it is no longer accessible whether it has been garbage collected or not.  In this sense, typical concepts of garbage collection are not really relevant. 

Once you have navigated backwards, the same instance of the page cannot be retrieved.  For instance, in the scenario where a user begins at MainPage.xaml and then navigates forward to DetailsPage.xaml, then navigates back to MainPage again, an additional navigation forward to DetailsPage.xaml will create a new instance of Details.  The original instance is lost and is no longer accessible.

To make matters more difficult, if the the application launches a task based on user input, the Details page is once again lost.  When the user clicks back to return to the application from a launcher or completes a chooser task, a new instance of DetailsPage will be created.  When the user clicks back from DetailsPage, a new instance of MainPage will be instantiated.  This termination of the current application in order to run task is known as “tombstoning”.

A final problem regarding state occurs if the phone application makes calls to web services.  Because web services are much more expensive and time sensitive than on typical web applications, it is highly desirable to cache data that has been retrieved from a service.

We’ll categorize these problems as problems of 1. page data state, 2. application data state and 3. model data state, respectively.

In this post I will outline three architectural patterns for solving these three problems of state in a Windows Phone application.  The patterns are View-ViewModel Pairing, Satellite ViewModels and Anchor ViewModels.

In the following posts, I will go in depth into the implementation each approach as well as provide helper classes and recommended coding patterns.  Finally, I will show how they can be incorporated into existing frameworks and techniques such as MVVM Light, Caliburn Micro and IOC.

I. View-ViewModel Pairing (Buddy System)

The View-ViewModel Pairing pattern is based on a persistence pattern recommended during the CTP stage of the Phone Development Tools.  In this pattern, each page or view (MainPage, DetailsPage, etc.) is responsible for the persistence of its data each time the page is added to or leaves the backstack. 

In the CTP, this was often illustrated by saving the data for a particular control on the view (current.State is used here, but isolated storage would work just as well):

string token = "myToken";

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
    {
        string txt = store[token] as string;
        if (txt != null)
            this.textBox1.Text = txt;
    }
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        store[token] = textBox1.Text;
    else
        store.Add(token, textBox1.Text);
}

This becomes cumbersome, however, if more than a few properties require persistence.  A better approach is possible if the phone application uses M-V-VM in its design (or really any UI Design Pattern that takes advantage of the DataContext property).  In this case, we can simply persist the entire VM rather than iterate through each control.  The above code can be simplified like this:

public Page1()
{
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(Page1_Loaded);
}

void Page1_Loaded(object sender, RoutedEventArgs e)
{
    if (this.DataContext == null)
        this.DataContext = new Page1ViewModel();
}

string token = "myToken";
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        this.DataContext = store[token] as string;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        store[token] = this.DataContext;
    else
        store.Add(token, this.DataContext);
}

This pattern collapses the problems of page data persistence and application data persistence by saving both off at the same time.

On the first navigation to this page, the Loaded event handler news up the datacontext.  On subsequent visits to the page, the DataContext is set in the OnNavigatedTo event handler.  Because Loaded fires after OnNavigatedTo, the DataContext is not set there.  Each visit to this page will always retrieve the same ViewModel data from state, whether the View is itself new or not.

This solution also works in cases where the application has been tombstoned.

If IsolatedStorage is used instead of PhoneApplicationService.Current.State, the ViewModel will even survive between runs of the application.

Finally, because any data retrieved from a web service is typically fed into an ObservableCollection on the ViewModel, the serialization/deserialization process will also typically take care of caching relevant model data.

There is one significant shortcomings to using the Buddy System.  Because there is no way (at least in the beta) to find out in the OnNavigatedTo event handler if we are returning from a tombstoned state or simply returning from a subsequent page through the back button, we may be re-hydrating the ViewModel unnecessarily.

(To be continued …)