×
Namespaces

Variants
Actions
(Difference between revisions)

Introduction and best practices for IsolatedStorageSettings

From Nokia Developer Wiki
Jump to: navigation, search
jinek (Talk | contribs)
(Jinek -)
jinek (Talk | contribs)
(Jinek -)
Line 55: Line 55:
 
     {
 
     {
 
         /// <summary>
 
         /// <summary>
         /// Object for syncing access to IsolatedStorageSettings resource
+
         /// Object for sync access to IsolatedStorage
 
         /// </summary>
 
         /// </summary>
 
         private readonly object _sync = new object();
 
         private readonly object _sync = new object();
Line 72: Line 72:
 
             }
 
             }
  
             //initializing the checkbox state
+
             //the checkbox state initializing
 
             chck.IsChecked = (bool) IsolatedStorageSettings.ApplicationSettings[SwitchKeyName];
 
             chck.IsChecked = (bool) IsolatedStorageSettings.ApplicationSettings[SwitchKeyName];
 
         }
 
         }
Line 122: Line 122:
 
     {
 
     {
 
         /// <summary>
 
         /// <summary>
         /// We must use this object to lock when saving settings
+
         /// We must use this object to lock saving settings
 
         /// </summary>
 
         /// </summary>
 
         public static readonly object ThreadLocker = new object();
 
         public static readonly object ThreadLocker = new object();
Line 130: Line 130:
  
 
     /// <summary>
 
     /// <summary>
     /// This is wrapper class for storing one settings.
+
     /// This is wrapper class for storing one setting
 
     /// Object of this type must be single
 
     /// Object of this type must be single
 
     /// </summary>
 
     /// </summary>
     /// <typeparam name="T">Any type that can be stored within IsolatedStorageSettings</typeparam>
+
     /// <typeparam name="T">Any serializable type</typeparam>
 
     public class IsolatedStorageProperty<T>
 
     public class IsolatedStorageProperty<T>
 
     {
 
     {
Line 147: Line 147:
  
 
         /// <summary>
 
         /// <summary>
         /// Determines if setting exists in storage
+
         /// Determines if setting exists in the storage
 
         /// </summary>
 
         /// </summary>
 
         public bool Exists
 
         public bool Exists
Line 248: Line 248:
 
         {
 
         {
 
             //MessageBox.Show - could freeze main thread for a long time
 
             //MessageBox.Show - could freeze main thread for a long time
             //Dont let it freeze in constructor
+
             //Dont let it freeze the constructor
 
             MessageBox.Show(FirstRunTimeProperty.Value.ToString());
 
             MessageBox.Show(FirstRunTimeProperty.Value.ToString());
             //This MessageBox always show time of first run
+
             //This MessageBox always shows time of first run
 
         }
 
         }
  

Revision as of 13:28, 9 November 2012

This article shows how to work with IsolatedStorageSettings.

WP Metro Icon File.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
CompatibilityArticle
Created: (16 Nov 2012)
Last edited: jinek (09 Nov 2012)

Contents

Introduction

In Windows Phone you have to store all your files and permanent values in special place - Isolated Storage (link). There is a special class for storing values: IsolatedStorageSettings. You can store there anything you want: user settings, layout state or value to determine if program us running first tume. In this tutorial we will create a simple application, that keeps a value in IsolatedStorageSettings and then extend it to look more professional.

Basic Sample

  1. Run Visual Studio 2012
  2. Create new Windows Phone project (7.5 or 8.0)
  3. Navigate to MainPage.xaml and replace all content with one checkbox:
<phone:PhoneApplicationPage x:Class="IsolatedStorageSample.MainPage"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}">
<CheckBox Content="Switch option"
Name="chck"
Checked="chck_Checked"
Unchecked="chck_Unchecked"
VerticalAlignment="Top" />
</phone:PhoneApplicationPage>
  1. Navigate to MainPage.xaml.cs and add some code here:
using System.IO.IsolatedStorage;
using System.Windows;
 
namespace IsolatedStorageSample
{
public partial class MainPage
{
/// <summary>
/// Object for sync access to IsolatedStorage
/// </summary>
private readonly object _sync = new object();
 
private const string SwitchKeyName = "switch";
 
// Constructor
public MainPage()
{
InitializeComponent();
//checking if property exists, if no - create it
if (!IsolatedStorageSettings.ApplicationSettings.Contains(SwitchKeyName))
{
IsolatedStorageSettings.ApplicationSettings[SwitchKeyName] = true;
SaveSettings();
}
 
//the checkbox state initializing
chck.IsChecked = (bool) IsolatedStorageSettings.ApplicationSettings[SwitchKeyName];
}
 
private void chck_Checked(object sender, RoutedEventArgs e)
{
IsolatedStorageSettings.ApplicationSettings[SwitchKeyName] = true;
SaveSettings();
}
 
private void chck_Unchecked(object sender, RoutedEventArgs e)
{
IsolatedStorageSettings.ApplicationSettings[SwitchKeyName] = false;
SaveSettings();
}
 
/// <summary>
/// Saving settings to isolated storage
/// </summary>
private void SaveSettings()
{
lock (_sync)
{
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
}
}
  1. Run the application

IsolatedStorageSettings is easy to use. But if you are going to behave more then just one setting - syncing, keeping key name, checking if setting exists and saving each time it was updated may became a headache. Better way is to provide all this functionality by helper class.

Improvement

As you can see, everything works fine. But we have to check if value in storage exists, we have to call Save every time we update anything and we have to use lock and finnaly we have to keep the property key name. More simplier way to work with IsolatedStorageSettings is to create a wrapper class around it. It will save the settings every time we update any value (in a thread safe way), it will automatically setup default value if setting does not exist (and does not throw an exception when you try to access not existent value), and finally it keeps the name of property - we have to provide it only once during property declaration. Create new class and name it IsolatedStorageProperty:

using System.IO.IsolatedStorage;
 
namespace IsolatedStorageSample
{
/// <summary>
/// Helper class is needed because IsolatedStorageProperty is generic and
/// can not provide singleton model for static content
/// </summary>
internal static class IsolatedStoragePropertyHelper
{
/// <summary>
/// We must use this object to lock saving settings
/// </summary>
public static readonly object ThreadLocker = new object();
 
public static readonly IsolatedStorageSettings Store = IsolatedStorageSettings.ApplicationSettings;
}
 
/// <summary>
/// This is wrapper class for storing one setting
/// Object of this type must be single
/// </summary>
/// <typeparam name="T">Any serializable type</typeparam>
public class IsolatedStorageProperty<T>
{
private readonly object _defaultValue;
private readonly string _name;
private readonly object _syncObject = new object();
 
public IsolatedStorageProperty(string name, T defaultValue = default(T))
{
_name = name;
_defaultValue = defaultValue;
}
 
/// <summary>
/// Determines if setting exists in the storage
/// </summary>
public bool Exists
{
get { return IsolatedStoragePropertyHelper.Store.Contains(_name); }
}
 
/// <summary>
/// Use this property to access the actual setting value
/// </summary>
public T Value
{
get
{
//If property does not exist - initializing it using default value
if (!Exists)
{
//Initializing only once
lock (_syncObject)
{
if (!Exists) SetDefault();
}
}
 
return (T) IsolatedStoragePropertyHelper.Store[_name];
}
set
{
IsolatedStoragePropertyHelper.Store[_name] = value;
Save();
}
}
 
private static void Save()
{
lock (IsolatedStoragePropertyHelper.ThreadLocker)
{
IsolatedStoragePropertyHelper.Store.Save();
}
}
 
public void SetDefault()
{
Value = (T) _defaultValue;
}
}
}

This class is pretty simple, but you can extend it as you want. Using is simple as well:

namespace IsolatedStorageSample
{
using System.Windows;
 
public partial class MainPage
{
static readonly IsolatedStorageProperty<bool> SwitchProperty = new IsolatedStorageProperty<bool>("switch",true);
 
public MainPage()
{
InitializeComponent();
chck.IsChecked = SwitchProperty.Value;
}
private void chck_Checked(object sender, RoutedEventArgs e)
{
SwitchProperty.Value = true;
}
 
private void chck_Unchecked(object sender, RoutedEventArgs e)
{
SwitchProperty.Value = false;
}
}
}

As you can see, a lot of lines of code are gone - very cool, when you store a lot of values. Lets create another setting: Good practice is to create a special static class, that will contain all your settings in it, so you can access any property in a program in any time you want, like this:

using System;
 
namespace IsolatedStorageSample
{
using System.Windows;
 
public partial class MainPage
{
static readonly IsolatedStorageProperty<bool> SwitchProperty = new IsolatedStorageProperty<bool>("switch",true);
 
/// <summary>
/// Keeps first run time
/// </summary>
static readonly IsolatedStorageProperty<DateTime> FirstRunTimeProperty = new IsolatedStorageProperty<DateTime>("firstruntime", DateTime.Now);
 
public MainPage()
{
InitializeComponent();
chck.IsChecked = SwitchProperty.Value;
Loaded+=OnLoaded;
}
 
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
//MessageBox.Show - could freeze main thread for a long time
//Dont let it freeze the constructor
MessageBox.Show(FirstRunTimeProperty.Value.ToString());
//This MessageBox always shows time of first run
}
 
private void chck_Checked(object sender, RoutedEventArgs e)
{
SwitchProperty.Value = true;
}
 
private void chck_Unchecked(object sender, RoutedEventArgs e)
{
SwitchProperty.Value = false;
}
}
}

FirstRunTimeProperty lets me know when was first application run.

Every time you run the application message box shows only first time you run it.

namespace IsolatedStorageSample
{
public static class SettingsContainer
{
public static readonly IsolatedStorageProperty<bool> TestProperty1
= new IsolatedStorageProperty<bool>("TestProperty1");
public static readonly IsolatedStorageProperty<string> TestProperty2
= new IsolatedStorageProperty<string>("TestProperty2", "This is a test property");
//...
}
}

The "platform categories" will be displayed here in preview only - Copy paste relevant categories into text here

Version Hint

Windows Phone: [[Category:Windows Phone]]
[[Category:Windows Phone 7.5]]
[[Category:Windows Phone 8]]

Nokia Asha: [[Category:Nokia Asha]]
[[Category:Nokia Asha Platform 1.0]]

Series 40: [[Category:Series 40]]
[[Category:Series 40 1st Edition]] [[Category:Series 40 2nd Edition]]
[[Category:Series 40 3rd Edition (initial release)]] [[Category:Series 40 3rd Edition FP1]] [[Category:Series 40 3rd Edition FP2]]
[[Category:Series 40 5th Edition (initial release)]] [[Category:Series 40 5th Edition FP1]]
[[Category:Series 40 6th Edition (initial release)]] [[Category:Series 40 6th Edition FP1]] [[Category:Series 40 Developer Platform 1.0]] [[Category:Series 40 Developer Platform 1.1]] [[Category:Series 40 Developer Platform 2.0]]

Symbian: [[Category:Symbian]]
[[Category:S60 1st Edition]] [[Category:S60 2nd Edition (initial release)]] [[Category:S60 2nd Edition FP1]] [[Category:S60 2nd Edition FP2]] [[Category:S60 2nd Edition FP3]]
[[Category:S60 3rd Edition (initial release)]] [[Category:S60 3rd Edition FP1]] [[Category:S60 3rd Edition FP2]]
[[Category:S60 5th Edition]]
[[Category:Symbian^3]] [[Category:Symbian Anna]] [[Category:Nokia Belle]]

Add categories below using category selector.

646 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×