Contents

  • Installation
  • Usage
  • Adding support for other types
  • Gotchas

Installation

  1. Download the library
  2. Add a reference to it in your project

Or use NuGet: http://www.nuget.org/List/Packages/WP7TombstoneHelper

Usage

Simple usage

Include a reference to the namespace:

using TombstoneHelper;

In any pages that have something you may want to preserve during tombstoning, simply call SaveState(e) in the OnNavigatingFrom handler and RestoreState() in the OnNavigatedTo handler.
Note that I'm using OnNavingatingFrom method, rather than OnNavigatedFrom, as it allows us to detect the direction of navigation. This means we don't save state if we know we won't need it again. This can help improve the performance of the app.

    protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
    {
        this.SaveState(e); 
    }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        this.RestoreState();
    }

Ensure that every object you want to be preserved has a Name specified.
The code below is from "TextBoxes.xaml" in the demo project included with the source. It shows three textboxes, the middle of which won't have it's text automatically preserved during tombstoning.

    <TextBlock Text="first (has name)" />
    <TextBox Name="first" />
    <TextBlock Text="second (doesn't have name)" />
    <TextBox /><!--This TextBox does not have a name so it's contents won't be automatically saved and restored -->
    <TextBlock Text="third (has name)" />
    <TextBox Name="third" />

That's it!

Slightly more advanced usage

If you want to improve performance you can specify only the types of the controls which you want to be preserved when calling SaveState().
eg:
    this.SaveState(typeof(TextBox), typeof(PasswordBox), typeof(CheckBox));
or
    this.SaveState(typeof(ScrollViewer));
or in a more generic style
    this.SaveState<ScrollViewer>();
or
    this.SaveState<ListBox, TextBox>();

Not only does this improve performance but it makes it easy to integrate this functionality to save some properties (typically the scroll position of a ListBox or ScrolViewer) where there is already a view model which preserves the data state.

Adding support for other types

  1. Add a new class to the project which implements ICanTombstone.
  2. Add the necessary code to implement the functionality. N.B. The key used for saving the state of the object should be a string comprising the name of the type and the name of the object separated by a '^' character.
  3. Add appropriate entries to AllTombstoneRestorers() and AllSupportedTombstoners() in "PhoneApplicationPageExtensions.cs".

If you are adding support for additional types then reviewing the exising implementations of ICanTombstone is highly recommended.


Gotchas

You may experience strange behaviour or unwanted side effects in the following situations
  • If you have an event that is triggered upon setting the property that automatically preserved. e.g. If it's a TextBox and you're handling the TextChanged event—it may have too account for it being triggered additional times.
  • If you are databinding the property which is has events or actions in response to setting it.
  • If you are generating the UI in code at runtime.
  • If you are also doing something with the State object yourself then do it after calling SaveState() as it will clear the contents of the state object to ensure it doen't have anything more than it needs in it.



If one of these scenarios does cause a problem then get in touch as there may be a workaround.

Last edited Sep 30, 2011 at 6:34 PM by mrlacey, version 10

Comments

orkazaz Jun 15, 2012 at 3:17 PM 
You can make life more easy for adding custom controls.
It's not enough to:
"Add appropriate entries to AllTombstoneRestorers() and AllSupportedTombstoners() in "PhoneApplicationPageExtensions.cs"."

Because in the AllSupportedTombstoners method the first thing is a foreach loop that checks if the control type exists in the property: "SupportedTypes".
Because we didn't add the new custom type to that list we will get an exception. Even if we did add the 2 enteries like written above:

// There will be errors if the unsupported types have been passed in the filter.
// Highlight this by raising an error
foreach (var type in filteredTypesToSave)
{
if (!SupportedTypes.Contains(type)
&& !TombstoneHelperExtensibility.CustomTombstoners.ContainsKey(type))
{
throw new ArgumentException(string.Format("TombstoneHelper doesn't know how to handle the type: {0}{1}You could create and register a custom tombstoner for this type or remove it from the list of types to use.", type.ToString(), System.Environment.NewLine));
}
}

You can fix it in 2 ways:
(1) Add the 2 enteries like you said AND add the new type to the SupportedTypes list property hardcoded.

OR

(2) At the begining of the method "AllSupportedTombstoners" (Before the type checker foreach) call a new static method, AND
also add the call for this method to begining of the "AllTombstoneRestorers" method.
/// <summary>
/// TODO: Register here all the custom tombstoners
/// </summary>
private static void RegisterAllCustomTombstoners()
{
TombstoneHelperExtensibility.RegisterCustomTombstoner(typeof(TextBlock), new TextBlockTombstoner());
}

this method uses the RegisterCustomTombstoner method inside the class "TombstoneHelperExtensibility".
I prefer the second option because you don't have to add the above written 2 enteries hardcoded for every new custome support for a new control.

Just add a single line to this new method :-)
And besides, this way the CustomTombstoners actually means something.

mrlacey Sep 30, 2011 at 6:36 PM 
@Pluginbaby - good spot. The base calls are acutally unnecessary as they don't actually do anything. Just a result of my Resharper generated code. The wrong method being called was a result of me not updating everything correctly. :(

Pluginbaby Sep 30, 2011 at 3:47 AM 
Awesome project!
There is a mistake in the sample of this page:

Replace:

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
this.SaveState(e);

base.OnNavigatedFrom();
}

With:

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
this.SaveState(e);

base.OnNavigatingFrom();
}