Windows Phone: adding settings to your app
Mood: cheerful
Posted on 2012-12-13 23:09:00
Tags: windowsphone wpdev
Words: 861

I like including a lot of settings in my apps - it gives the user a lot of control about how the app looks/behaves. But it's a little tedious to add the code to save them to Isolated Storage, notify when they've changed, and allowing the user to change them on a settings page. After just doing this for a new release of PhotoNotes, I thought I'd write a step-by-step guide to adding settings to an app.

In this example, I was adding a boolean setting for whether PhotoNotes's tile should be live. So, let's get started!

Step 1: Add a UserSettings class

This class will provide access to the settings and handle saving/loading to Isolated Storage, as well as have an event for when the settings have changed.

Here's the actual UserSettings class for PhotoNotes. If you prefer you can also download UserSettings.cs here.


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.Collections.ObjectModel;

namespace NoteLens.wp8
{
public class UserSettings
{
IsolatedStorageSettings settings;
public event EventHandler SettingsChanged;

const string TilePictures = "TilePictures";

const bool TilePicturesDefault = true;

public bool ShowTilePictures
{
get
{
return GetValueOrDefault(TilePictures, TilePicturesDefault);
}
set
{
if (AddOrUpdateValue(TilePictures, value))
{
Save();
}
}
}

public static UserSettings Instance = null;
// This can't be private because it's called from the XAML in App.xaml,
// but don't create one of these in code!
public UserSettings()
{
try
{
settings = IsolatedStorageSettings.ApplicationSettings;
if (Instance == null)
{
Instance = this;
}
else
{
System.Diagnostics.Debug.Assert(false,
"Created multiple UserSettings!");
}
}
catch (Exception)
{
settings = null;
}
}

///
/// Update a setting value for our application. If the setting does not
/// exist, then add the setting.
///

///
///
///
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;

// If the key exists
if (settings.Contains(Key))
{
// If the value has changed
if (settings[Key] != value)
{
// Store the new value
settings[Key] = value;
valueChanged = true;
}
}
// Otherwise create the key.
else
{
settings.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}

///
/// Get the current value of the setting, or if it is not found, set the
/// setting to the default setting.
///

///
///
///
///
public T GetValueOrDefault<T>(string Key, T defaultValue)
{
T value;

// If the key exists, retrieve the value.
if (settings.Contains(Key))
{
value = (T)settings[Key];
}
// Otherwise, use the default value.
else
{
value = defaultValue;
}
return value;
}

///
/// Save the settings.
///

public void Save()
{
settings.Save();
EventHandler settingsChanged = SettingsChanged;
if (settingsChanged != null)
{
settingsChanged(this, new EventArgs());
}
}

}
}


The bottom part of this file (from the constructor down) is pretty boilerplate. If you want to add a new setting, all you have to do is define a new key name (like TilePictures here), a new default value (like TilePicturesDefault) and the name of the property that exposes it (like ShowTilePictures) - then you can just copy and paste the existing property and make the three replacements.

Step 2: Define a resource for your UserSettings

This will let you easily access the UserSettings from XAML and code.

In your App.xaml, first make sure you have a namespace added for wherever your UserSettings class is. I didn't, so I had to add
    xmlns:nl="clr-namespace:NoteLens.wp8"

to my <Application> tag.

Then, inside the <Application.Resources> tag, add

        <nl:UserSettings x:Key="appSettings"/>  


Step 3: Add a control to change the setting to a page

I already had an About page in the app (possible future post!) which used a Pivot control, so I just made the settings a new PivotItem under that.

The best way to show a Boolean value is to use a ToggleSwitch, which is part of the Windows Phone toolkit which is put out by Microsoft. So first, make sure you have that installed - I had to install it with NuGet. Now, here's the XAML for adding the new PivotItem and control:
  
<controls:PivotItem Header="settings">
<StackPanel Orientation="Vertical">
<toolkit:ToggleSwitch IsChecked="
{Binding Source={StaticResource appSettings},
Path=ShowTilePictures, Mode=TwoWay}">
Live Tile
</toolkit:ToggleSwitch>
</StackPanel>
</controls:PivotItem>

Here we're binding to the appSettings resource we declared in step 2, and through the magic of data binding this will show the current value of the setting and also let the user change it.

Step 4: Listen for when the setting changes

We're almost done! In this case, I wanted to know when the user changed the setting so I could immediately update the tile to make it live or not. So, in About.xaml.cs (the codebehind for the About page) I made the following changes:

To OnNavigatedTo(), added
            UserSettings.Instance.SettingsChanged += appSettings_SettingsChanged; 

To OnNavigatedFrom(), added
            UserSettings.Instance.SettingsChanged -= appSettings_SettingsChanged; 

And finally added the method:

void appSettings_SettingsChanged(object sender, EventArgs e)
{
Util.UpdateLiveTile();
}

Step 5: Use the setting in code

This is obviously very app-dependent, but to get the value of the setting in code you should use

UserSettings.Instance.ShowTilePictures

It's important to always use UserSettings.Instance and not create a new UserSettings class instance to access the settings, otherwise your SettingsChanged events might not fire in the right places. I added an assert to ensure that we only ever create one of them, and that will happen when the app resources are created from App.xaml.


In this example, we just added a boolean setting - see this follow-up post for adding an enum-like setting.

--

See all my Windows Phone development posts.

I'm planning on writing more posts about Windows Phone development - what would you like to hear about? Reply here, on twitter at @gregstoll, or by email at ext-greg.stoll@nokia.com.

--

Interested in developing for Windows Phone? I'm the Nokia Developer Ambassador for Austin - drop me a line at ext-greg.stoll@nokia.com!


This backup was done by LJBackup.