Visually Located

XAML and GIS

Strongly type your settings saved in IsolatedStorageSettings

When creating an app you’ll need some way to save user settings. In Windows Phone (and Windows Store) Apps there are four possible ways to save settings.

  1. Key/Value pairs in IsolatedStorageSettings
  2. Save a file in IsolatedStorage
  3. Save values in a local database
  4. Save values in the cloud

Usually everyone starts by saving values into IsolatedStorageSettings, and for the most part, it’s probably the best way to go. If you are creating a music app, you can not use IsolatedStorageSettings. The AudioPlayerAgent simply will not get the correct setting values. If you are creating an app with a background agent, you should consider not using IsolatedStorageSettings for the same reason as before. You are less likely to have a problem with incorrect values with a normal background agent than you are when using an audio agent.

While using the IsolatedStorageSettings can be easy, the code can get ugly fast. You may have usage scattered throughout your code.

public MainPage()
{
    InitializeComponent();
 
    IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
    bool useLocation;
    if (settings.TryGetValue("UseLocation", out useLocation) == false)
    {
        useLocation = true;
    }
 
    // do something with the setting
}

Eventually you’ll get tired of all of this code everywhere and probably create a class and wrap the access within the properties.

public class Settings
{
    public bool UseLocation
    {
        get
        {
            IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
            bool useLocation;
            if (settings.TryGetValue("UseLocation", out useLocation) == false)
            {
                useLocation = true;
            }
            return useLocation;
        }
        set
        {
            IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
            settings["UseLocation"] = value;
            settings.Save();
        }
    }
 
    public double SomeOtherValue
    {
        get
        {
            IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
            double someOtherValue;
            settings.TryGetValue("SomeOtherValue", out someOtherValue);
            return someOtherValue;
        }
        set
        {
            IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
            settings["SomeOtherValue"] = value;
            settings.Save();
        }
    }
}

As you can see this eventually gets out of control. Let’s take this one step further. Instead of littering our code with all of this dictionary access, why don’t we just create a class with automatic properties that has a Save and Load method.

public class Settings
{
    public bool UseLocation { get; set; }
 
    public double SomeOtherValue { get; set; }
 
    public void Save()
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
        settings["UseLocation"] = UseLocation;
        settings["SomeOtherValue"] = SomeOtherValue;
        settings.Save();
    }
 
    public void Load()
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
 
        bool useLocation;
        if (settings.TryGetValue("UseLocation", out useLocation) == false)
        {
            useLocation = true;
        }
        UseLocation = useLocation;
 
        double someOtherValue;
        settings.TryGetValue("SomeOtherValue", out someOtherValue);
        SomeOtherValue = someOtherValue;
    }
}

Our code got a little better, but it’s not very extensible. Every time you add a new property you have to add keys/values to saving and loading. When you write your next app, you’ll copy and paste the file and change the strings. I enjoy reusing code, not copy/paste. I enjoy doing less work, not adding key/values for every setting property I have.

We can make this even better. We can make a reusable class, in which we do not have to worry about adding more than our auto properties. We do this with reflection and a base class.

public class Settings
{
    public void Save()
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
        PropertyInfo[] properties = GetType().GetProperties();
        foreach (var property in properties)
        {
            settings[property.Name] = property.GetValue(this);
        }
 
        settings.Save();
    }
 
    public void Load()
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
        PropertyInfo[] properties = GetType().GetProperties();
        foreach (var property in properties)
        {
            if (settings.Contains(property.Name))
            {
                property.SetValue(this, settings[property.Name]);
            }
        }
    }
}

Now that we have a base class for settings, we can create an instance of settings that are unique for our application. All this file needs is the properties that define the application settings.

public class AppSettings : Settings
{
    public AppSettings()
    {
        // default to true, let the user override this value
        UseLocation = true;
    }
 
    public bool UseLocation { get; set; }
 
    public double SomeOtherValue { get; set; }
}

With this approach, you’ll want to make sure that you load and save your settings when needed. I personally like to create a static method/property that creates my settings and loads the values.

Note: You could just save the file itself in iso settings rather than each property, but that is not the point of this post :-)

blog comments powered by Disqus