The APIs of Windows Phone 7 offer a lot of comfort when it comes to accessing and using them, however, some of them can still be improved. During writing some apps for the Windows Phone 7 I got somehow annoyed always accessing the isolated storage. But before I come to my helper class which I created for my own, what exactly is the isolated storage?
Isloated Storage allows only access to your own data
The isolated storage is your one and only possibility to access and save your App’s data. On the WP7 there is no other opportunity to persist data on the phone (the only alternative is using webservices on your own server and have a communication by raw or toast messages with the application). Furthermore you cannot access any data from other apps on the phone. You have only access to your own saved data. The data in the isolated storage is allocated dynamically. This means “first come first serve”. The app that’s allocating first is getting the space on the storage.
There are two different kinds of access points in the storage
The isolated storage gives you two possibilities to access the isolated storage. Firstly, the local settings which is just a Dictionary with a key-value pair of string-object. This allows you to store easily the settings of your app. For example “Which is the standard RSS-feed?” (for a RSS reader app). How to access it see the code below:
var ObjToLoad if (IsolatedStorageSettings.ApplicationSettings.Contains("SomeKey")) { ObjToLoad = (T)IsolatedStorageSettings.ApplicationSettings["SomeKey"]; }
As you can see accessing is pretty straight forward. And so is saving the settings:
if (!IsolatedStorageSettings.ApplicationSettings.Contains("SomeKey")) { IsolatedStorageSettings.ApplicationSettings.Add("SomeKey", SomeSetting); } else { IsolatedStorageSettings.ApplicationSettings["SomeKey"] = SomeSetting; }
So there is no rocket science about it. To actually save your data is a bit more lines of codes but still not any kind of a witch craft:
// Load the object from an xml-file using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { if (isf.FileExists("SomeFileName")) { using (IsolatedStorageFileStream fs = isf.OpenFile("SomeFileName.xml", System.IO.FileMode.Open)) { XmlSerializer ser = new XmlSerializer(ObjectToDeSerialize); ObjToLoad = (T) ser.Deserialize(fs); } } } // Save the object to an xml-file using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream fs = isf.OpenFile("SomeFileName.xml", System.IO.FileMode.Create)) { writer = new StreamWriter(fs); XmlSerializer ser = new XmlSerializer(typeof(T)); ser.Serialize(writer, ObjectToSave); writer.Close(); } }
What actually happens here is that I get the pointer which gives me the location of the isolated storage of my app. With that filestream I get back I can check if my file does exist and open or create it. Then i am using a simple XML serializer to serialize or deserialize any object I want to be saved. This here is very straight forward and doen’t have to be the best solution. In fact, due to the overhead which XML produces I would recommend to use JSON data instead of XML. But for not too big amount of data XML is just fine!
Make it shorter and more universal
But it is a bit annoying to always write or copy and paste the whole checking and to create new file names for new objects to be saved. Instead of that you could just use my helper class which i wrote. This class is just a beginning and should show you how it could look like. I am using it for myself and for simple saving processes.
Important to say before i give you my code is, that i am not worrying about filenames. I autogenerate the file name by using typeof(T).FullName. In this case the file gets always the same name if the object (by structure) is the same. You could use other possibilities but I wanted to have it as short as possible and not worrying about the file names. But now to the code (which can also be downloaded at the end of this post):
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; using System.Xml.Serialization; using System.IO; namespace Reader_Online_News.Helper { public class PersistHelper { public static T LoadObjectFromStorage<T>() { T ObjToLoad = default(T); try { using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { if (isf.FileExists(GetFileName<T>())) { using (IsolatedStorageFileStream fs = isf.OpenFile(GetFileName<T>(), System.IO.FileMode.Open)) { XmlSerializer ser = new XmlSerializer(typeof(T)); ObjToLoad = (T) ser.Deserialize(fs); } } } } catch (Exception error) { throw new NotImplementedException(error.Message); } return ObjToLoad; } public static void SaveObjectToStorage<T>(T ObjectToSave) { TextWriter writer; using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream fs = isf.OpenFile(GetFileName<T>(), System.IO.FileMode.Create)) { writer = new StreamWriter(fs); XmlSerializer ser = new XmlSerializer(typeof(T)); ser.Serialize(writer, ObjectToSave); writer.Close(); } } } public static string GetFileName<T>() { return typeof(T).FullName+".xml"; } public static bool IsObjectPersisted<T1>() { using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { return isf.FileExists(GetFileName<T1>()); } } public static T LoadSetttingFromStorage<T>(string Key) { T ObjToLoad = default(T); if (IsolatedStorageSettings.ApplicationSettings.Contains(Key)) { ObjToLoad = (T)IsolatedStorageSettings.ApplicationSettings[Key]; } return ObjToLoad; } public static void SaveSettingToStorage(string Key, object Setting) { if (!IsolatedStorageSettings.ApplicationSettings.Contains(Key)) { IsolatedStorageSettings.ApplicationSettings.Add(Key, Setting); } else { IsolatedStorageSettings.ApplicationSettings[Key] = Setting; } } public static bool IsSettingPersisted(string Key) { return IsolatedStorageSettings.ApplicationSettings.Contains(Key); } } }
And here the code for Download:
Download PersistHelper.cs
Michael
This is really good! Thanks! I’m a newbie and I’m having a problem with the LoadObjectFromStorage part: I’m looking at the code, but I can’t really figure out how to emplement the method. For example, saving is
PersistHelper.SaveObjectToStorage(MyObject); but how would I load MyObject from storage into whatever MyObject is? thanks.
Christophe
Hi, Same question of Michael…
Sebastian Schütze
No Problem. This solution is a very simple one. The Name of the file that will serialized is dependent on the type of the object you want to save. That makes it easy to save but there is a drawback. You can only save one instance of a class. The last instance of a object will overwrite any instance you saved before. Hope that helps.