Windows Phone 7 XML IsolatedStorage Example


For one of the apps I have been working on, I needed to persist a List<T> of T objects across sessions. They are simple objects with simple properties, so I decided to use XML. However, since WP7 is a new platform, there’s not a lot of information out there on what is a good best practice.

It turns out for simple situations like mine, serializing objects into XML and writing that to file is by far the easiest way to do it.

Let’s examine a scenario.

The App

This is not an app I am working on, but it is basically the same thing.

Let’s say that you want to track your jogs. Starting simple, you decide to track the following properties:

  • RouteID : int
  • Duration : TimeSpan (we will encounter an interesting serialization bug with TimeSpan as well)
  • Date : DateTime
  • Distance (miles) : float

Of course, we won’t attempt to build all of this here, but rather, focus on the storage aspect of it.

The “Jog” Object

You will persist a list of these objects to be able to view them historically. This is what a Jog object might look like. Note the extra property, DurationXml, with its special attributes – this exists because XmlSerializer does not properly serialize TimeSpan objects.

    public class Jog
    {
        private TimeSpan _duration = new TimeSpan();

        public DateTime Date { get; set; }

        [XmlIgnore]
        public TimeSpan Duration
        {
            get { return _duration; }
            set { _duration = value; }
        }

        // HACK: This property only exists for XML serialization.
        // It gets serialized as a <Duration> tag.
        [XmlElement("Duration", DataType="duration")]
        public string DurationXml
        {
            get
            {
                return XmlConvert.ToString(_duration);
            }
            set
            {
                if (value == null)
                {
                    _duration = TimeSpan.Zero;
                    return;
                }

                TimeSpan newDuration = XmlConvert.ToTimeSpan(value);
                if (_duration == newDuration)
                    return;
                _duration = newDuration;
            }
        }

        public int RouteID { get; set; }
        public float Distance { get; set; }
    }

Note the hackery around the Duration and DurationXml properties.

Jog List

For the purposes of this app, you’d have a List of Jog objects: List<Jog> which you keep as a static on the App class and maintain it there. You’d then create some methods in the App class that would help out with storage, and then call them from Application_Closing, Application_Launching, and Activated/Deactivated as you handle tombstoning and deactivation.

Storage Helper

Then, you might write a class like this which helps with storage, and keep it statically on the App class. All you have to do is call XmlSerializer.Serialize(object) and XmlHelper.Deserialize(xml) to manage the saving/loading of your object list. Put together, it looks like this:

    public class StorageHelper
    {
        private const string FILE_NAME = "Jogs.xml";

        public List<Jog> LoadJogs()
        {
            List<Jog> jogs = new List<Jog>();
            TextReader reader = null;
            try
            {
                IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
                IsolatedStorageFileStream file = isoStorage.OpenFile(FILE_NAME, FileMode.OpenOrCreate);

reader = new StreamReader(file);

 


                XmlSerializer xs = new XmlSerializer(typeof(List<Jog>));
                jogs.AddRange((List<Jog>)xs.Deserialize(reader));
                reader.Close();                
            }
            catch
            {
                
            }
            finally
            {
                if (reader != null)
                    reader.Dispose();                
            }

            return jogs;
        }

        public void SaveJogs(List<Jog> jogs)
        {
            TextWriter writer = null;
            try
            {
                IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
                IsolatedStorageFileStream file = isoStorage.OpenFile(FILE_NAME, FileMode.Create);
                writer = new StreamWriter(file);

                XmlSerializer xs = new XmlSerializer(typeof(List<Jog>));
                xs.Serialize(writer, jogs);
                writer.Close();
            }
            catch
            {

            }
            finally
            {
                if (writer != null)
                    writer.Dispose();
            }
        }

        public StorageHelper()
        {

        }
    }

Don’t Forget Your References

One thing to note here is that several of the Xml classes won’t magically work with IntelliSense. You need to add references to System.Xml and System.Xml.Serialization for all this good stuff to work.

I’ll be posting an example Jog Tracker application that uses isolated storage in the coming weeks, but for now, this should be enough to get you started.

Comments (9)

  1. Surf4Fun says:

    Excellent posting!  I am writing a series on using UML in Visual Studio 2010 Ultimate at:

    http://bit.ly/alMGtu

  2. Surf4Fun says:

    Excellent posting!  I am writing a series on using UML in Visual Studio 2010 Ultimate at:

    http://bit.ly/alMGtu

  3. Drew Freyling says:

    Nice post. I'd only suggest to use using statements for IsolatedStorageFile and IsolatedStorageFileStream as they implement IDisposable.

  4. Jason Dool says:

    This seems to directly contridict the MSDN documentation for win7 phone.

    msdn.microsoft.com/…/system.xml.serialization.xmlserializer(v=VS.95).aspx

    It states you can't use xmlserializer on an ArrayList or List<T>.

  5. Jason Dool says:

    This seems to directly contridict the MSDN documentation for win7 phone.

    msdn.microsoft.com/…/system.xml.serialization.xmlserializer(v=VS.95).aspx

    It states you can't use xmlserializer on an ArrayList or List<T>.

  6. dawate says:

    Hey Jason,

    The documentation states that it can't serialize arrays of ArrayList or arrays of List<T>. This means you can't serialize arrays where every element is another array. This example only deals with one-dimensional arrays.

  7. MatsyDoodles says:

    You mentioned you would be posting an example Jog Tracker application, I was just wondering if you ever got round to it?

  8. alf says:

    orale k padre x sierto saves como guardar y leer informacion  de un txt en windows phone game 4.0????

  9. dawate says:

    @alf: Puede guardar cualquier tipo de datos en almacenamiento aislado. No debe estar en formato XML. Sin embargo, esto es la forma más fácil de hacerlo. Mis disculpas por gramática incorrecta; Esto viene de una herramienta de traductor.