Tuesday, September 14, 2010

Windows Phone 7 Quick Tip #3 – Use a NavDictionary to pass state between pages

I’ve fallen in love with the page navigation model in Windows Phone 7, it seems very natural.  One of the challenges with this is maintaining state between pages.  In the server side equivalent, IDs are used to lookup the state as each page is served up.  This works well on the server, but can be wasteful in a client application.  Another option is to use global variables to store state…nope.

Here’s my solution, it seems to work well, but I’d be interested in hearing other approaches.

Firstly - create a simple class to maintain state between pages, this class has two methods, an Add and a Get.  The Add will add the instance to a dictionary and return an ID that can be used to pass a reference between pages.  The Get will do a lookup based upon that ID and return the instance.  In my case I decided to always remove the item up on a Get.  Your approach might be different.  Using generics makes this even cleaner.

using System;
using System.Collections.Generic;

namespace MyWP7App
{
    public class NavDictionary
    {
        private static Dictionary<Guid, object> _dictionary = new Dictionary<Guid, object>();

        public static Guid Add(object o)
        {
            var id = Guid.NewGuid();
            _dictionary.Add(id, o);

            return id;
        }

        public static T Get<T>(Guid g) where T : class       
        {
            var item = _dictionary[g] as T;

            _dictionary.Remove(g);

            return item;
        }

    }
}

Then for the implementation:

To add an item:

var id = NavDictionary.Add(myObject);

NavigationService.Navigate(new Uri(string.Format("/MyPage.xaml?id={0}", id), UriKind.Relative));

And to get the item back out, simply call the Get method in the OnNavigatedTo event (or wherever it makes sense to for your application).

var myObject = NavDictionary.Get<MyType>
                 (new Guid(NavigationContext.QueryString["id"]));

Remember my Get implementation will yank the item out of the dictionary so it can only be called once, this works and make sense for my implementation.  You need to think how your application is implemented to take into account backwards navigation and tombstoning.

-twb

3 comments:

  1. Great post! I use IOC to pass data - http://dotnetcatch.wordpress.com/2010/09/15/wp7-sharing-data-between-pages-with-mvvm/

    What do you think?

    ReplyDelete
  2. how is it different from using a global variable? You are using the static dictionary similar to a global variable.

    ReplyDelete
  3. And what about getting added structures ?
    Why did you add
    "where T : class" constraint ?

    ReplyDelete