I received a few questions at an event recently as to how to handle application settings in a Windows 8 Store app and how it is different from doing so in a Windows Store app. Turns out there is a lot of similarity, in the code as well as the platform offering for storing them, but Windows 8 does have some unique capabilities and challenges.

A settings page in a Windows Phone app is pretty easy. You basically create an additional XAML page in your app to provide the UI for the user to view and change settings. If you use the IsolatedStorageSettings class you get a nice, simple way to store name/value pairs of settings associated with your application.

Here’s a simple example of managing settings in a Windows Phone project. In this app we’re storing a boolean for whether the customer is tax exempt, the state they live in, their preferred shipping speed, and their email address. The class AppSettings (below) manages saving and retrieving our sample settings.

using System;
using System.Diagnostics;

using System.IO.IsolatedStorage;

namespace SettingsDemo
{
public class AppSettings
{


// Our isolated storage settings
IsolatedStorageSettings isolatedStore;

// The isolated storage key names of our settings
const string TaxExemptSettingKeyName = "TaxExemptSetting";
const string StateSettingKeyName = "StateSetting";
const string NextDayShippingSettingKeyName = "NextDayShippingSetting";
const string TwoDayShippingSettingKeyName = "TwoDayShippingSetting";
const string GroundShippingSettingKeyName = "GroundShippingSetting";
const string EmailSettingKeyName = "UsernameSetting";


// The default value of our settings
const bool TaxExemptSettingDefault = true;
const int StateSettingDefault = 0;
const bool NextDayShippingSettingDefault = true;
const bool TwoDayShippingSettingDefault = false;
const bool GroundShippingSettingDefault = false;
const string EmailSettingDefault = "";


/// <summary>
/// Constructor that gets the application settings.
/// </summary>
public AppSettings()
{
try
{
// Get the settings for this application.
isolatedStore = IsolatedStorageSettings.ApplicationSettings;

}
catch (Exception e)
{
Debug.WriteLine("Exception while using IsolatedStorageSettings: " + e.ToString());
}
}

/// <summary>
/// Update a setting value for our application. If the setting does not
/// exist, then add the setting.
/// </summary>
/// <param name="Key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;

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

return valueChanged;
}


/// <summary>
/// Get the current value of the setting, or if it is not found, set the
/// setting to the default setting.
/// </summary>
/// <typeparam name="valueType"></typeparam>
/// <param name="Key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public valueType GetValueOrDefault<valueType>(string Key, valueType defaultValue)
{
valueType value;

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

return value;
}


/// <summary>
/// Save the settings.
/// </summary>
public void Save()
{
isolatedStore.Save();
}


/// <summary>
/// Property to get and set a CheckBox Setting Key.
/// </summary>
public bool TaxExemptSetting
{
get
{
return GetValueOrDefault<bool>(TaxExemptSettingKeyName, TaxExemptSettingDefault);
}
set
{
AddOrUpdateValue(TaxExemptSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a ListBox Setting Key.
/// </summary>
public int StateSetting
{
get
{
return GetValueOrDefault<int>(StateSettingKeyName, StateSettingDefault);
}
set
{
AddOrUpdateValue(StateSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool NextDayShippingSetting
{
get
{
return GetValueOrDefault<bool>(NextDayShippingSettingKeyName, NextDayShippingSettingDefault);
}
set
{
AddOrUpdateValue(NextDayShippingSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool TwoDayShippingSetting
{
get
{
return GetValueOrDefault<bool>(TwoDayShippingSettingKeyName, TwoDayShippingSettingDefault);
}
set
{
AddOrUpdateValue(TwoDayShippingSettingKeyName, value);
Save();
}
}

/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool GroundShippingSetting
{
get
{
return GetValueOrDefault<bool>(GroundShippingSettingKeyName, GroundShippingSettingDefault);
}
set
{
AddOrUpdateValue(GroundShippingSettingKeyName, value);
Save();
}
}

/// <summary>
/// Property to get and set a Username Setting Key.
/// </summary>
public string EmailSetting
{
get
{
return GetValueOrDefault<string>(EmailSettingKeyName, EmailSettingDefault);
}
set
{
AddOrUpdateValue(EmailSettingKeyName, value);
Save();
}
}


}
}


Notice that we need to call the .Save() method on the IsolatedStorageSettings instance when the properties are updated.

This settingsPage.xaml gives us the UI for the user to change the app’s settings.

<phone:PhoneApplicationPage 
x:Class="SettingsDemo.settingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

xmlns:local="clr-namespace:SettingsDemo"

FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">

<phone:PhoneApplicationPage.Resources>
<local:AppSettings x:Key="appSettings"></local:AppSettings>
</phone:PhoneApplicationPage.Resources>

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="SETTINGS DEMO" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="settings" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Margin="30,0,0,0">
<CheckBox Content="Tax Exempt" Height="Auto" HorizontalAlignment="Left" Name="TaxExemptSetting" VerticalAlignment="Top"
IsChecked="{Binding Source={StaticResource appSettings}, Path=TaxExemptSetting, Mode=TwoWay}" />

<TextBlock Margin="0,25, 0, 0" Text="State:" TextWrapping="Wrap" HorizontalAlignment="Left"/>
<ListBox Margin="0,7, 0, 0" HorizontalAlignment="Left"
SelectedIndex="{Binding Source={StaticResource appSettings}, Path=StateSetting, Mode=TwoWay}"
>
<ListBoxItem Content="Georgia"/>
<ListBoxItem Content="Alabama"/>
<ListBoxItem Content="Florida"/>
</ListBox>



<TextBlock Margin="0,25, 0, 0" Text="Shipping speed:" TextWrapping="Wrap" HorizontalAlignment="Left"/>
<RadioButton Content="Overnight" Height="Auto" HorizontalAlignment="Left" Margin="0,0,0,0" Name="NextDayShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=NextDayShippingSetting, Mode=TwoWay}" />
<RadioButton Content="Two day" Height="Auto" HorizontalAlignment="Left" Margin="0,0,0,0" Name="TwoDayShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=TwoDayShippingSetting, Mode=TwoWay}"/>
<RadioButton Content="Ground" Height="Auto" HorizontalAlignment="Left" Margin="0,0,0,0" Name="GroundShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=GroundShippingSetting, Mode=TwoWay}"/>


<TextBlock Height="36" HorizontalAlignment="Left" Margin="0,0,0,0" Name="textBlock1" Text="email address" VerticalAlignment="Top" Width="169" />
<TextBox Name="textBoxEmail" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Width="274"
Text="{Binding Source={StaticResource appSettings}, Path=EmailSetting, Mode=OneWay}"/>

</StackPanel>
</Grid>
</Grid>



</phone:PhoneApplicationPage>

In here we’re data binding the visual elements to the properties in the AppSettings class. We’ve declared an instance of that class in the Resources section of the file. Our controls are data bound two-way so when the user updates them, they write back to the class. We don’t do that for the textbox, because that’s a lot of writes while the user is typing. Instead, when the page is navigated away from, we update the class. Here’s the code behind where that happens.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;

namespace SettingsDemo
{
public partial class settingsPage : PhoneApplicationPage
{
public settingsPage()
{
InitializeComponent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
AppSettings settings = (AppSettings)this.Resources["appSettings"];

settings.EmailSetting = textBoxEmail.Text;
}
}
}

Here’s a screenshot of the thing running.

settingsscreen

One thing you’ll notice about this approach is that it conforms to the UI paradigm for modern apps. That is, there is no “OK/Cancel” button for settings, as was in the past. When the user makes setting changes, they should both be saved right away, and also take effect in the app right away. The former is accomplished by simply calling .Save() on the underlying IsolatedStorageSettings.

OK, so what about the concept of settings in a Windows Store app? We’ll need to save them, and in that regard, Windows Store is very similar to Windows Phone. Our AppSettings class above comes over to a Windows Store project with very few changes.

using System;
using System.Diagnostics;
using Windows.Storage;

namespace WPMigrateSettingsDemo
{
class AppSettings
{
// Our isolated storage settings
//IsolatedStorageSettings isolatedStore;
ApplicationDataContainer localSettings;

// The isolated storage key names of our settings
const string TaxExemptSettingKeyName = "TaxExemptSetting";
const string StateSettingKeyName = "StateSetting";
const string NextDayShippingSettingKeyName = "NextDayShippingSetting";
const string TwoDayShippingSettingKeyName = "TwoDayShippingSetting";
const string GroundShippingSettingKeyName = "GroundShippingSetting";
const string EmailSettingKeyName = "UsernameSetting";


// The default value of our settings
const bool TaxExemptSettingDefault = true;
const int StateSettingDefault = 0;
const bool NextDayShippingSettingDefault = true;
const bool TwoDayShippingSettingDefault = false;
const bool GroundShippingSettingDefault = false;
const string EmailSettingDefault = "";


/// <summary>
/// Constructor that gets the application settings.
/// </summary>
public AppSettings()
{
try
{
localSettings = ApplicationData.Current.LocalSettings;
// Get the settings for this application.
//isolatedStore = IsolatedStorageSettings.ApplicationSettings;

}
catch (Exception e)
{

}
}

/// <summary>
/// Update a setting value for our application. If the setting does not
/// exist, then add the setting.
/// </summary>
/// <param name="Key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;

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

return valueChanged;
}


/// <summary>
/// Get the current value of the setting, or if it is not found, set the
/// setting to the default setting.
/// </summary>
/// <typeparam name="valueType"></typeparam>
/// <param name="Key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public valueType GetValueOrDefault<valueType>(string Key, valueType defaultValue)
{
valueType value;

// If the key exists, retrieve the value.
if (localSettings.Values.ContainsKey(Key))
{
value = (valueType)localSettings.Values[Key];
}
// Otherwise, use the default value.
else
{
value = defaultValue;
}

return value;
}


/// <summary>
/// Save the settings.
/// </summary>
public void Save()
{
//isolatedStore.Save();

}


/// <summary>
/// Property to get and set a CheckBox Setting Key.
/// </summary>
public bool TaxExemptSetting
{
get
{
return GetValueOrDefault<bool>(TaxExemptSettingKeyName, TaxExemptSettingDefault);
}
set
{
AddOrUpdateValue(TaxExemptSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a ListBox Setting Key.
/// </summary>
public int StateSetting
{
get
{
return GetValueOrDefault<int>(StateSettingKeyName, StateSettingDefault);
}
set
{
AddOrUpdateValue(StateSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool NextDayShippingSetting
{
get
{
return GetValueOrDefault<bool>(NextDayShippingSettingKeyName, NextDayShippingSettingDefault);
}
set
{
AddOrUpdateValue(NextDayShippingSettingKeyName, value);
Save();
}
}


/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool TwoDayShippingSetting
{
get
{
return GetValueOrDefault<bool>(TwoDayShippingSettingKeyName, TwoDayShippingSettingDefault);
}
set
{
AddOrUpdateValue(TwoDayShippingSettingKeyName, value);
Save();
}
}

/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool GroundShippingSetting
{
get
{
return GetValueOrDefault<bool>(GroundShippingSettingKeyName, GroundShippingSettingDefault);
}
set
{
AddOrUpdateValue(GroundShippingSettingKeyName, value);
Save();
}
}

/// <summary>
/// Property to get and set a Username Setting Key.
/// </summary>
public string EmailSetting
{
get
{
return GetValueOrDefault<string>(EmailSettingKeyName, EmailSettingDefault);
}
set
{
AddOrUpdateValue(EmailSettingKeyName, value);
Save();
}
}

}
}

We use the Windows.Storage namespace instead of System.IO.IsolatedStorage and we use ApplicationData.Current.LocalSettings (an ApplicationDataContainer) instead of IsolatedStorageSettings.ApplicationSettings. The rest of the code refers to localSettings.Values instead of isolatedStore but the rest is the same.

In this sample I sought to mimic the Windows Phone settings capabilities, but it’s worth noting that in Windows Store apps, you can keep settings local (to the app on that machine) or roaming (with the user’s Microsoft ID automatically). Here are some good guidelines on using roaming app data.

How about the user interface aspect? Well, this requires us to connect into the Settings charm to display the settings screen for our app. So instead of simply navigating to a Settings.xaml page, we have to work with the SettingsPane. It is a little tricky to set up, but it creates a better experience for accessing settings within Windows Store apps for users.

First, we have to create a user control in our Windows Store project that’s going to contain the UI elements similar to the settings page in our Windows Phone app. We add a new User Control called SettingsFlyout to the project and use this XAML.

<UserControl
x:Class="WPMigrateSettingsDemo.SettingsFlyout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WPMigrateSettingsDemo"


xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">



<UserControl.Resources>
<local:AppSettings x:Key="appSettings"></local:AppSettings>
<Style x:Key="SettingsBackButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="26.66667"/>
<Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Width="30" Height="30">
<Grid Margin="-6,-6,0,0">
<TextBlock x:Name="BackgroundGlyph" Text="&#xE0D4;" Foreground="Transparent"/>
<TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="White"/>
<TextBlock x:Name="ArrowGlyph" Text="&#xE0C4;" Foreground="#00b2f0" Opacity="0"/>
</Grid>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"
/>

<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"
/>

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ArrowGlyph"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="NormalGlyph"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>

<Border BorderBrush="#00b2f0" BorderThickness="1,0,0,0">
<Grid Background="DarkBlue" VerticalAlignment="Stretch">

<!-- Root grid definition -->
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<!-- Header area for panel -->
<Grid Background="#00b2f0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<StackPanel Orientation="Horizontal" Grid.Column="0" Margin="40, 32, 17, 13">
<Button Click="MySettingsBackClicked" Margin="6,3,0,0" Style="{StaticResource SettingsBackButtonStyle}"/>
<TextBlock Margin="10,0,0,0" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="Options" Foreground="White"/>
<Image Source="Assets/smalltile-sdk.png" Margin="400,0,6,0"/>
</StackPanel>
</Grid>

<!-- Settings Panel Content -->
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">
<Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.RowSpan="3">

<StackPanel x:Name="FlyoutContent">
<CheckBox Content="Tax Exempt" Height="Auto" HorizontalAlignment="Left" Name="TaxExemptSetting" VerticalAlignment="Top"
IsChecked="{Binding Source={StaticResource appSettings}, Path=TaxExemptSetting, Mode=TwoWay}" />

<TextBlock Margin="0,25, 0, 0" Text="State:" TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"/>
<ComboBox Margin="0,7, 0, 0" HorizontalAlignment="Left"
SelectedIndex="{Binding Source={StaticResource appSettings}, Path=StateSetting, Mode=TwoWay}"
>
<ComboBoxItem Content="Georgia"/>
<ComboBoxItem Content="Alabama"/>
<ComboBoxItem Content="Florida"/>
</ComboBox>



<TextBlock Margin="0,25, 0, 0" Text="Shipping speed:" TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"/>
<RadioButton Content="Overnight" Height="Auto" HorizontalAlignment="Left" Margin="0,20,0,0" Name="NextDayShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=NextDayShippingSetting, Mode=TwoWay}" />
<RadioButton Content="Two day" Height="Auto" HorizontalAlignment="Left" Margin="0,20,0,0" Name="TwoDayShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=TwoDayShippingSetting, Mode=TwoWay}"/>
<RadioButton Content="Ground" Height="Auto" HorizontalAlignment="Left" Margin="0,20,0,0" Name="GroundShipping" VerticalAlignment="Top" GroupName="GroupOne" IsChecked="{Binding Source={StaticResource appSettings}, Path=GroundShippingSetting, Mode=TwoWay}"/>


<TextBlock Height="60" HorizontalAlignment="Left" Margin="0,20,0,0" Name="textBlock1" Text="email address" VerticalAlignment="Top" Width="169" />
<TextBox Name="textBoxEmail" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Width="274"
Text="{Binding Source={StaticResource appSettings}, Path=EmailSetting, Mode=OneWay}" LostFocus="textBoxEmail_LostFocus_1"/>

</StackPanel>
</Grid>
</ScrollViewer>
</Grid>

</Border>
</UserControl>

When the settings screen is accessed from the app, it will look like this.

screenshot_09162012_233118

There’s a <resources> section at the top that is related to the behavior and appearance of the back button at the top, which closes the settings pane. The rest of the XAML defines the controls on the page, almost the same way they do in Windows Phone (except I changed the list box to a combo box). The same data binding is used to an instance of the AppSettings class declared the same way at the top of the XAML file.

The user control has some code to deal with saving the data in the text box when it loses focus, as well as some UI things for when the user navigates away from the panel, or clicks the back button with the app snapped.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace WPMigrateSettingsDemo
{
public sealed partial class SettingsFlyout : UserControl
{
// The guidelines recommend using 100px offset for the content animation.
const int ContentAnimationOffset = 100;
public SettingsFlyout()
{
this.InitializeComponent();
FlyoutContent.Transitions = new TransitionCollection();
FlyoutContent.Transitions.Add(new EntranceThemeTransition()
{
FromHorizontalOffset = (SettingsPane.Edge == SettingsEdgeLocation.Right) ? ContentAnimationOffset : (ContentAnimationOffset * -1)
});
}
private void MySettingsBackClicked(object sender, RoutedEventArgs e)
{

// First close our Flyout.
Popup parent = this.Parent as Popup;
if (parent != null)
{
parent.IsOpen = false;
}

// If the app is not snapped, then the back button shows the Settings pane again.
if (Windows.UI.ViewManagement.ApplicationView.Value != Windows.UI.ViewManagement.ApplicationViewState.Snapped)
{
SettingsPane.Show();
}
}

private void textBoxEmail_LostFocus_1(object sender, RoutedEventArgs e)
{
AppSettings settings = (AppSettings)this.Resources["appSettings"];
settings.EmailSetting = textBoxEmail.Text;
}
}
}

The biggest difference in the setting system between Windows Phone and Windows 8 is how this app settings UI ties into the Settings charm. There are a few ways to go about this, but I chose to connect the settings capability to the MainPage.xaml. In that page’s constructor, I added an event handler for the CommandsRequested event from the settings pane, so when the user invokes the Settings charm, we can add choices in the list. In that handler, we tell the system to add an Options command to the settings pane, and give it some code to run when that Options command is invoked. In this example I used a lambda expression to define a new Popup and fill the popup with an instance of the user control I defined above. We do a few other things to position the Popup and the user control properly based on screen resolution. Here’s the code behind for the mainpage.xaml file.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace WPMigrateSettingsDemo
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private Rect _windowBounds;
private Popup _settingsPopup;
private double _settingsWidth = 346;

public MainPage()
{
this.InitializeComponent();

_windowBounds = Window.Current.Bounds;

SettingsPane.GetForCurrentView().CommandsRequested += myCommandsRequested;
}


void myCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{

SettingsCommand cmd = new SettingsCommand("options", "Options",

(x) =>
{
_settingsPopup = new Popup();
_settingsPopup.Closed += OnPopupClosed;
Window.Current.Activated += OnWindowActivated;
_settingsPopup.IsLightDismissEnabled = true;
_settingsPopup.Width = _settingsWidth;
_settingsPopup.Height = _windowBounds.Height;

SettingsFlyout mypane = new SettingsFlyout();
mypane.Width = _settingsWidth;
mypane.Height = _windowBounds.Height;

_settingsPopup.Child = mypane;
_settingsPopup.SetValue(Canvas.LeftProperty, _windowBounds.Width - _settingsWidth);
_settingsPopup.SetValue(Canvas.TopProperty, 0);
_settingsPopup.IsOpen = true;

});


args.Request.ApplicationCommands.Add(cmd);
}

private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
{
if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
{
_settingsPopup.IsOpen = false;
}
}

void OnPopupClosed(object sender, object e)
{
Window.Current.Activated -= OnWindowActivated;
}

}
}

One more note on roaming settings. Right now, settings don’t roam between Windows Phones (because users generally have only one phone anyway) or between Windows 8 and Windows Phone apps. If you wanted to accomplish something like that, you’d have to roll your own cloud-based settings system.

Fundamentally, the approach for handling settings in a Windows Phone app and a Windows 8 app are quite similar. Hooking into the settings charm is a great way to integrate with the Windows 8 user experience, but the underlying way to set and retrieve them is the same.