C#, WinRT

Save objects to the ‘LocalFolder’

IMPORTANT: You find the newest versions of TCD.Serialization on NuGet – it works with Windows Phone as well.


This post will Show you how to serialize and save objects with XML to your apps LocalFolder/RoamingFolder.
Metro style apps in Windows 8 have their own folders where they can store their data. These folders can be accessed by:

StorageFolder localFolder = ApplicationData.Current.LocalFolder; 
StorageFolder roamingFolder = ApplicationData.Current.RoamingFolder;

The difference between these two folders is that Windows 8 will synchronise the RoamingFolder between different machines. This can be useful if you want to improve the user experience, for example by synchronising drafts of a blog post between a users tablet and PC.
It’s very important, that the data you want to save is serializable. When designing the data structure and classes for your data, you got to make sure, that each class has a parameterless constructor. Properties can be marked with a set of attributes from the System.XML.Serialization namespace such as [XmlElement], [XmlAttribute] or [XmlIgnore].
In this example I will use the following class for simplicity:

public class Person
{
    [XmlAttribute]
    public string Name { get; set; }
    [XmlElement]
    public string Biography { get; set; }
}

Let’s assume that we have a List<Person> that we want to save to a file called “persons.xml”. I use my TCD.Serialization.XmlDeSerializer to do this. You can find it on NuGet. (instructions how to use  NuGet)

public static async Task SaveAsync(List<Person> persons)
{
    StorageFile file = await localFolder.CreateFileAsync("persons.xml", CreationCollisionOption.OpenIfExists);
    try
    {
        XmlDeSerializer.SerializeToStream(await file.OpenStreamForWriteAsync(), persons);
    }
    catch
    { }
}

To load the data we use this method:

public static async Task<List<Person>> LoadAsync()
{
    StorageFile file = await localFolder.CreateFileAsync("persons.xml", CreationCollisionOption.OpenIfExists);
    List result = null;
    try
    {
        result = XmlDeSerializer.DeserializeFromStream(await file.OpenStreamForReadAsync(), typeof(List<Person>)) as List<Person>;
    }
    catch
    { }
    return result;
}

EDIT: As smeyac pointed out in the comment below, you can serialize objects into the ApplicationData.Current.LocalSettings (or .RoamingSettings) as well. Take a look at his comment for some code.

Both approaches have the advantages and disadvantages, so you should always have both in mind!

Have fun =)

5 comments

  1. smeyac

    Hi,
    I just discovered your blog. Nice to see that I’m not the only “Öcher guy” developing for Windows 8 😉

    However, there’s a much more convient way accessing the local data store. Have a look at the ApplicationDataContainer e.g.

    // create it once.
    // localContainer, located in ApplicationData.Current.LocalFolder
    var local = ApplicationData.Current.LocalSettings;
    ApplicationDataContainer myContainer;
    if ( local.Containers.ContainsKey( “myContainer” ) )
    {
    myContainer = local.Containers[“myContainer”];
    }
    else
    {
    myContainer = = local.CreateContainer( “myContainer”, ApplicationDataCreateDisposition.Always );
    }

    // serialize data
    SerializeableObject obj = new SerializeableObject();
    myContainer.Values.Add( “key”, obj );
    myContainer.Values[“key”] = anotherObj;

    // deserialize data
    SerializeableObject obj = (SerializeableObject)myContainer.Values[“key”];

    1. smeyac

      Unfortunately there’s no edit function.
      There’s an error in the code above.
      It should be:
      ApplicationDataContainer myContainer = local.CreateContainer( “myContainer”, ApplicationDataCreateDisposition.Always );
      There’s no need to check for it’s existence. The framework will do it by itself.

    2. thecake

      Hey,
      Actually I’m no ‘real Öcher’ – I just happen to study here^ x)

      You’re right I should’ve mentioned this as well and will update the post as soon as I’m back home.
      Nevertheless I can think of scenarios where you want to save objects to a file in a way that you, as a developer, can access it. For example media files, GPX files or like me: the serialized version of the RWTH Mensa Speiseplan (the mensa menu..)
      cheers^

  2. shen

    if the person table has a collection property for example Tasks which is a List, and Task is another Class. How can we serialize List persons then?

    1. thecake

      the List property would get the [XmlElement] attribute and the properties of the Task class should get XmlElement/XmlAttribute/XmlIgnore… as well.

Leave a Reply

Your email address will not be published. Required fields are marked *