In this post I am going to implement IsolatedStorageSettings in WPF.
Lets start with a brief introduction to IsolatedStorageSettings, Its a storage which is used for storing application configurations and it uses IsolatedStore to store those setting. Its a builtin feature in Silverlight but not available in WPF. In WPF we have ApplcationSettings , but it uses App.config to store application settings.
Why do we need IsolatedStorageSetting in WPF ?
We had a requirement where user should be able to store application setting but user will not have access to read/write any file including App.config file so we needed to be able to read write these settings at a path where users will always have access irrespective of their security settings.
Lets look at code below
1) I am going to create a new class CustomIsolatedStorageSettings which will be derived from IDictionary<string,Object>. we are deriving it from IDictionary because we want it to be like a dictionary object where we should be able to store object against their keys.
2) I am going to have use Singleton design patter to expose this class, that's why i have made private constructor and used a static constructor which initializes Instance property and also custom appDictionary object which is used to store all keys and objects.
3) I have a ReadData method which is called in static constructor , it reads file from IsolatedStorage and sets key values in appDictionary. It reads file CustomIsolatedStorage.bin which is stored in binary format and deserializes into appDictionary.
4) I have a Save method which is called whenever any key is updated. It formats appDictionary in a binary stream and saves that stream using IsolatedStorageStream in CustomIsolatedStorage.bin file.
Lets start with a brief introduction to IsolatedStorageSettings, Its a storage which is used for storing application configurations and it uses IsolatedStore to store those setting. Its a builtin feature in Silverlight but not available in WPF. In WPF we have ApplcationSettings , but it uses App.config to store application settings.
Why do we need IsolatedStorageSetting in WPF ?
We had a requirement where user should be able to store application setting but user will not have access to read/write any file including App.config file so we needed to be able to read write these settings at a path where users will always have access irrespective of their security settings.
Lets look at code below
1) I am going to create a new class CustomIsolatedStorageSettings which will be derived from IDictionary<string,Object>. we are deriving it from IDictionary because we want it to be like a dictionary object where we should be able to store object against their keys.
2) I am going to have use Singleton design patter to expose this class, that's why i have made private constructor and used a static constructor which initializes Instance property and also custom appDictionary object which is used to store all keys and objects.
3) I have a ReadData method which is called in static constructor , it reads file from IsolatedStorage and sets key values in appDictionary. It reads file CustomIsolatedStorage.bin which is stored in binary format and deserializes into appDictionary.
4) I have a Save method which is called whenever any key is updated. It formats appDictionary in a binary stream and saves that stream using IsolatedStorageStream in CustomIsolatedStorage.bin file.
/// <summary> /// This class is implemented to store user settings in an Isolated storage file. /// </summary> public class CustomIsolatedStorageSettings : IDictionary<string,Object> { #region Constants/Variables static Dictionary<string, object> appDictionary = new Dictionary<string, object>(); static CustomIsolatedStorageSettings CustomIsolatedStorageSettings = new CustomIsolatedStorageSettings(); const string filename = "CustomIsolatedStorage.bin"; #endregion #region Singleton Implementation /// <summary> /// Its a private constructor. /// </summary> private CustomIsolatedStorageSettings() { } /// <summary> /// Its a static singleton instance. /// </summary> public static CustomIsolatedStorageSettings Instance { get { return CustomIsolatedStorageSettings; } } /// <summary> /// Its static constructor. /// </summary> static CustomIsolatedStorageSettings() { LoadData(); } private static void LoadData() { IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null); if ( isoStore.GetFileNames(filename).Length == 0 ) { // File not exists. Let us NOT try to DeSerialize it. return; } // Read the stream from Isolated Storage. Stream stream = new IsolatedStorageFileStream( filename,FileMode.OpenOrCreate, isoStore ); if ( stream != null ) { try { // DeSerialize the Dictionary from stream. IFormatter formatter = new BinaryFormatter(); Dictionary<string,Object> appData = ( Dictionary<string,Object>) formatter.Deserialize(stream); // Enumerate through the collection and load our Dictionary. IDictionaryEnumerator enumerator = appData.GetEnumerator(); while ( enumerator.MoveNext() ) { appDictionary[enumerator.Key.ToString()] = enumerator.Value; } } finally { stream.Close(); } } } #endregion #region Methods /// <summary> /// It serializes dictionary in binary format and stores it in a binary file. /// </summary> public void Save() { IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null); Stream stream = new IsolatedStorageFileStream(filename,FileMode.Create, isoStore ); if ( stream != null ) { try { // Serialize dictionary into the IsolatedStorage. IFormatter formatter = new BinaryFormatter(); formatter.Serialize( stream, appDictionary ); } finally { stream.Close(); } } } /// <summary> /// It Checks if Dictionary object has item corresponding to passed key, /// if True then it returns that object else it returns default value. /// </summary> /// <param name="key"></param> /// <param name="defaultvalue"></param> /// <returns></returns> public object this[string key, Object defaultvalue] { get { if (appDictionary.ContainsKey(key)) { return appDictionary[key]; } else { return defaultvalue; } } set { appDictionary[key] = value; Save(); } } #endregion #region IDictionary<string, object> Members public void Add(string key, object value) { appDictionary.Add(key, value); Save(); } public bool ContainsKey(string key) { return appDictionary.ContainsKey(key); } public ICollection<string> Keys { get { return appDictionary.Keys; } } public bool Remove(string key) { try { Save(); appDictionary.Remove(key); return true; } catch { return false; } } public bool TryGetValue(string key, out object value) { return appDictionary.TryGetValue(key, out value); } public ICollection<object> Values { get { return appDictionary.Values; } } public object this[string key] { get { return appDictionary[key]; } set { appDictionary[key] = value; Save(); } } public void Add(KeyValuePair<string, object> item) { appDictionary.Add(item.Key, item.Value); } public void Clear() { appDictionary.Clear(); Save(); } public bool Contains(KeyValuePair<string, object> item) { return appDictionary.ContainsKey(item.Key); } public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) { throw new NotImplementedException(); } public int Count { get { return appDictionary.Count; } } public bool IsReadOnly { get { return false; } } public bool Remove(KeyValuePair<string, object> item) { return appDictionary.Remove(item.Key); } public IEnumerator<KeyValuePair<string, object>> GetEnumerator() { return appDictionary.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return appDictionary.GetEnumerator(); } #endregion }
Thank you very much, it helps me in MonoGame, where this class does not implemented
ReplyDeleteMy hack version
http://pastebin.com/u3p7x36W