Mobile Zone is brought to you in partnership with:

Mikael is the founder of Adafy Oy, a Finnish software startup providing development services for Windows Phone, Windows 8 and Windows Azure. Adafy is available for hire: www.adafy.com. Mikael is a DZone MVB and is not an employee of DZone and has posted 46 posts at DZone. You can read more from them at their website. View Full User Profile

Windows Phone: How to Easily Store User Settings

01.04.2013
| 2581 views |
  • submit to reddit

Here’s a base class for Windows Phone apps which I’ve been using to store user settings. It wraps the IsolatedStorageSettings and it’s a slightly modified version of the SettingsStore-class included in the “A Case Study for Building Advanced Windows Phone Applications – Code Samples”. Here’s an example of how to use the base class (in a Windows Phone 8 app):

public class MySettingsStore : SettingsStore
{
    public bool IsFirstAppStart
    {
        get { return this.GetValueOrDefault(true); }
        set { this.AddOrUpdateValue(value); }
    }
 
    public string FirstName
    {
        get { return this.GetValueOrDefault(""); }
        set { this.AddOrUpdateValue(value); }
    }
}

The class can be used store more complex objects too, as long as they are serializable:

[DataContract]
public class User
{
    [DataMember]
    public string Name { get; set; }
}
 
public class MySettingsStore : SettingsStore
{
    public List<User> Users
    {
        get { return this.GetValueOrDefault(new List<User>()); }
        set { this.AddOrUpdateValue(value); }
    }
}

The GetValueOrDefault-method takes one parameter and this is the default value which is returned if no stored setting is found.

In your app you can store a setting using the following code:

var settingsStore = new MySettingsStore();
...
settingsStore.FirstName = this.FirstNameTextBox.Text;

And to read a setting (or the default value):

var settingsStore = new MySettingsStore();
...
this.FirstNameTextBox.Text = settingsStore.FirstName;

Here’s the full code for the base class SettingsStore. It uses the CallerMemberName to automatically deduct the key for a setting.

using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Runtime.CompilerServices;
 
namespace Adafy.Infra
{
    public class SettingsStore
    {
        private readonly IsolatedStorageSettings isolatedStore;
 
        public SettingsStore()
        {
            this.isolatedStore = IsolatedStorageSettings.ApplicationSettings;
        }
 
        protected void AddOrUpdateValue(object value, [CallerMemberName]string key = "key")
        {
            var valueChanged = false;
 
            lock (this)
            {
 
                try
                {
                    if (value == null)
                    {
                        // Nothing to remove
                        if (!this.isolatedStore.Contains(key))
                            return;
 
                        this.isolatedStore.Remove(key);
                        this.Save();
                    }
 
                    // If the new value is different, set the new value.
                    if (this.isolatedStore[key] != value)
                    {
                        this.isolatedStore[key] = value;
                        valueChanged = true;
                    }
                }
                catch (KeyNotFoundException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
                catch (ArgumentException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
 
                if (valueChanged)
                {
                    this.Save();
                }
            }
        }
 
        protected T GetValueOrDefault<T>(T defaultValue, [CallerMemberName]string key = "key")
        {
            lock (this)
            {
 
                T value;
 
                try
                {
                    value = (T)this.isolatedStore[key];
                }
                catch (KeyNotFoundException)
                {
                    value = defaultValue;
                }
                catch (ArgumentException)
                {
                    value = defaultValue;
                }
 
                return value;
            }
 
        }
 
        private void Save()
        {
            try
            {
                this.isolatedStore.Save();
            }
            catch (Exception)
            {
                return;
            }
        }
    }
 
}

SettingsStore for Windows Phone 7

CallerMemberName isn’t available in Windows Phone 7. Because of this, each settings must provide an unique key:

public class MySettingsStore : SettingsStore
{
    private const string FirstAppStartKey = "MyKey";
    private const string FirstNameKey = "MyKey2";
 
    public bool IsFirstAppStart
    {
        get { return this.GetValueOrDefault(true, FirstAppStartKey); }
        set { this.AddOrUpdateValue(value, FirstAppStartKey); }
    }
 
    public string FirstName
    {
        get { return this.GetValueOrDefault("", FirstNameKey); }
        set { this.AddOrUpdateValue(value, FirstNameKey); }
    }
}

Here’s the full code for WP7 version of the SettingsStore, which is nearly identical to the one provided in Prism.

using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Runtime.CompilerServices;
 
namespace Adafy.Infra
{
    public class SettingsStore
    {
        private readonly IsolatedStorageSettings isolatedStore;
 
        public SettingsStore()
        {
            this.isolatedStore = IsolatedStorageSettings.ApplicationSettings;
        }
 
        protected void AddOrUpdateValue(object value, [CallerMemberName]string key = "key")
        {
            var valueChanged = false;
 
            lock (this)
            {
 
                try
                {
                    if (value == null)
                    {
                        // Nothing to remove
                        if (!this.isolatedStore.Contains(key))
                            return;
 
                        this.isolatedStore.Remove(key);
                        this.Save();
                    }
 
                    // If the new value is different, set the new value.
                    if (this.isolatedStore[key] != value)
                    {
                        this.isolatedStore[key] = value;
                        valueChanged = true;
                    }
                }
                catch (KeyNotFoundException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
                catch (ArgumentException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
 
                if (valueChanged)
                {
                    this.Save();
                }
            }
        }
 
        protected T GetValueOrDefault<T>(T defaultValue, [CallerMemberName]string key = "key")
        {
            lock (this)
            {
 
                T value;
 
                try
                {
                    value = (T)this.isolatedStore[key];
                }
                catch (KeyNotFoundException)
                {
                    value = defaultValue;
                }
                catch (ArgumentException)
                {
                    value = defaultValue;
                }
 
                return value;
            }
 
        }
 
        private void Save()
        {
            try
            {
                this.isolatedStore.Save();
            }
            catch (Exception)
            {
                return;
            }
        }
    }
}

The SettingsStore classes could be combined with the help of conditional compilation.




Published at DZone with permission of Mikael Koskinen, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)