Tombstoning and MVVM

We’re working pretty hard to get the Who Is That (Full Stack) Windows Phone application tombstone_istock ready. Today I took a look at tombstoning and realized that this was not going to be quite as easy as I thought… and worse, the problem was  MVVM.

The key problem is that the easy way to handle tombstoning is with Page State, which is not available to the ViewModel, but it is the ViewModel that knows what is to be stored.

I came up with a solution, but be warned, this is a first attempt and may not be the best way to handle this.

The spec says that if the user takes a specific set of actions I need to restore any fields that the user has already filled out.  That is, if the user

  • Fills in some fields
  • Switches to another application or calls a launcher or chooser
  • Uses the back button to return

…the fields already filled in should still be filled. 

On the other hand, if the user takes the first two steps, but comes back to the application from the start menu, then the fields should be blank (as that counts as a re-start rather than a return).

The good news is that you can tie your tombstoning to the OnNavigatedTo and OnNavigatedFrom events. The bad news is that only the View has these events, the ViewModel does not, and it is the ViewModel that has the information to preserve; that is, the state of its properties (which the View binds to).

As noted, if you were not using MVVM this would be simple; you place the value of the controls into the Page’s state and the rest is automagic: if you return the values are there, if you re-start the values are not there and you therefore know just what to do.

Unfortunately, that page state is not available to the ViewModel. If the VM is doing the storing it is doing it in Isolated Storage, and Isolated Storage does not differentiate between restore and restart, your values will persist in either case.  There is no easy way for the ViewModel to automatically know if it should restore the values or not. Someone has to tell it.

Then she picked out two somebodies, Sally and Me.

I chose to have the VM own responsibility for saving and restoring state from Isolated Storage, but have the View own responsibility for when to ask the VM to save and when to restore or reinitialize. Thus, in the VM I created three methods:

  • Tombstone (save state to isolated storage)
  • Restore (retrieve state from isolated storage)
  • Init (do not retrieve state from isolated storage)
 internal void Tombstone( )
 {
    WhoIsThatWinPhone.AppServices.IsoStorage.Add( 
          "Contact", _contact );
 }

 internal void Restore( )
 {
    _contact = System.IO.IsolatedStorage
               .IsolatedStorageSettings
               .ApplicationSettings[ "Contact" ] 
                as WhoIsThatWinPhone.Model.Person;
 }
internal void Init( )
{
       InitializeNewContact( );
   }

This is nice and clean and these methods can be called from the OnNavigatedFrom and OnNavigatedTo methods in the view.  But, how does the OnNavigatedTo method know whether to call Restore or Init?

My decision was to take advantage of the fact that Page.State is a reliable bell-weather. If content stored in the page’s state is still there, then we are returning; if it is removed, then we are restarting.  Thus, I add a flag to the page’s state just before telling the View Model to store the state. 

(In this code, _vm is a private member variable in the view that holds a reference to the view model). 

 protected override void OnNavigatedFrom( 
    System.Windows.Navigation.NavigationEventArgs e )
 {
    this.State[ "tombstone" ] = true;
    _vm.Tombstone( );
    base.OnNavigatedFrom( e );
 }

 

When I come to the page, I check whether that flag exists in the page state. If so, then I’m returning, otherwise I’m restarting:

protected override void OnNavigatedTo( 
   System.Windows.Navigation.NavigationEventArgs e )
{
   if ( this.State.ContainsKey( "tombstone" ) )
   {
      _vm.Restore( );
   }
   else
   {
      _vm.Init( );
   }

   base.OnNavigatedTo( e );
}

 

I’ll be interested in comments that indicate a better or cleaner way to do this, though this certainly works, and is pretty straightforward to understand. 

The only alternative that appeals is to pass the entire page state to the VM in each method call, and let the ViewModel play with the PageState.  But that seems like an ugly mixing of a view collection and the ViewModel.

Your thoughts?

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen Pluralsight & LinkedIn Learning courses. He was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP and a Microsoft MVP.
This entry was posted in Data, Full Stack, Mini-Tutorial, WindowsPhone and tagged . Bookmark the permalink.