×
Namespaces

Variants
Actions
(Difference between revisions)

Introduction and best practices for IsolatedStorageSettings

From Nokia Developer Wiki
Jump to: navigation, search
jinek (Talk | contribs)
(Jinek -)
hamishwillee (Talk | contribs)
m (Hamishwillee -)
(41 intermediate revisions by 7 users not shown)
Line 1: Line 1:
[[Category:Draft]]
+
[[Category:Files/Data on Windows Phone]][[Category:Windows Phone 7.5]][[Category:Windows Phone 8]][[Category:Code Examples]][[Category:XAML]]
{{Abstract|This article shows how to work with IsolatedStorageSettings.}}
+
{{Abstract|This article explains how to use  [http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstoragesettings(v=vs.95).aspx IsolatedStorageSettings] and illustrates a helper class which enables using saving & retrieving (many) settings parameters easily.}}
{{ArticleMetaData v1.0
+
{{SeeAlso|
|sourcecode=[[File:IsolatedStorageSample.zip]]
+
[[Saving application preferences in Windows Phone]]
 +
}}
 +
{{ArticleMetaData <!-- v1.2 -->
 +
|sourcecode= [[File:IsolatedStorageSample.zip]]
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
 
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
|sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Qt SDK 1.1.4]) -->
+
|sdk= [https://dev.windowsphone.com/en-us/downloadsdk WP SDK 8.0]
|platform= <!-- Compatible platforms - e.g. Symbian^1 and later, Qt 4.6 and later -->
+
|platform= Windows Phone 7.5 and 8.0
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->  
+
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
|signing=<!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
+
|signing= <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
|keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase -->
+
|keywords= IsolatedStorageSettings, Isolated Storage, User Settings
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|translated-by= <!-- [[User:XXXX]] -->
 
|translated-by= <!-- [[User:XXXX]] -->
|translated-from-title= <!-- Title only -->  
+
|translated-from-title= <!-- Title only -->
 
|translated-from-id= <!-- Id of translated revision -->
 
|translated-from-id= <!-- Id of translated revision -->
|review-by=<!-- After re-review: [[User:username]] -->
+
|review-by= <!-- After re-review: [[User:username]] -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 
|update-by= <!-- After significant update: [[User:username]]-->
 
|update-by= <!-- After significant update: [[User:username]]-->
 
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 
|update-timestamp= <!-- After significant update: YYYYMMDD -->
|creationdate= <!-- Format YYYYMMDD -->
+
|creationdate= 20121109
|author= <!-- Display as link [[User:username]] -->
+
|author= [[User:jinek]]
 
}}
 
}}
  
 
== Introduction ==
 
== 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,
+
[http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstoragesettings(v=vs.95).aspx IsolatedStorageSettings] is a dictionary for permanent storing values in  [http://msdn.microsoft.com/en-us/library/x7dzh4ws(v=vs.95).aspx Isolated Storage] in the form of ''key-value pair''. All that you have to do to store a value - is to provide a key for this value and a value itself.
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.
+
You can store anything you want that is serializable, for example: user settings, layout information or application state. All settings from {{Icode|IsolatedStorageSettings}} are accessible after application shutdown and run again.
== Basic Sample ==
+
 
 +
In this tutorial we will create a simple application that keeps one boolean value and then we are going to extend it for more convenient use.
 +
 
 +
== Storing one setting with IsolatedStorageSettings ==
 
# Run Visual Studio 2012
 
# Run Visual Studio 2012
# Create new Windows Phone project (7.5 or 8.0)
+
# Create new Windows Phone project (7.1 or 8.0)
#Navigate to MainPage.xaml and replace all content with one checkbox:
+
# Navigate to '''MainPage.xaml''' and replace all control content with one checkbox: <code xml>
<code xml><phone:PhoneApplicationPage x:Class="IsolatedStorageSample.MainPage"
+
<phone:PhoneApplicationPage x:Class="IsolatedStorageSample.MainPage"
 
                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 
                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Line 45: Line 51:
 
               Unchecked="chck_Unchecked"
 
               Unchecked="chck_Unchecked"
 
               VerticalAlignment="Top" />
 
               VerticalAlignment="Top" />
</phone:PhoneApplicationPage></code>
+
</phone:PhoneApplicationPage>
#Navigate to MainPage.xaml.cs and add some code here:
+
</code>
<code csharp>using System.IO.IsolatedStorage;
+
# Navigate to '''MainPage.xaml.cs''' and insert code for storing and retrieving the value: <code csharp>
 +
using System.IO.IsolatedStorage;
 
using System.Windows;
 
using System.Windows;
  
Line 100: Line 107:
 
     }
 
     }
 
}</code>
 
}</code>
#Run the application
+
# Run the application
<gallery>
+
#: As expected - the checkbox remembers last state before application shutdown.
File:IsolatedStorageIntro.SimpleApplication.png|Simple setting
+
#: [[File:IsolatedStorageIntro.SimpleApplication.png|200px|Simple setting]]
</gallery>
+
 
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.
+
Why do I use thread synchronization?  Because I do not know where else I will decide to call {{Icode|SaveSettings}} in the future, it could be {{Icode|ThreadPool}}, Timer callback or anything else.
== Improvement ==
+
{{Icode|IsolatedStorageSettings}} is easy to use.  
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.
+
But if you are going to have more than just one setting-value - syncing, keeping key name, checking if setting exists and saving each time it has been updated may become a headache. Better way is to implement all this functionality in a helper class only once.
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.
+
== Helper class for easy storage of more setting values==
Create new class and name it IsolatedStorageProperty:
+
 
<code csharp>using System.IO.IsolatedStorage;
+
Now we are going to create new class and implement logic for storing and retrieving setting values. With this, it should save the setting values every time we update it (in a thread safe manner), it should automatically set the default value if setting does not exist and finally it should keep the key name - we have to provide it only once at property declaration.
 +
 
 +
We create two new classes: {{Icode|IsolatedStoragePropertyHelper}} and {{Icode|IsolatedStorageProperty}} as illustrated below.
 +
 
 +
<code csharp>
 +
using System.IO.IsolatedStorage;
  
 
namespace IsolatedStorageSample
 
namespace IsolatedStorageSample
Line 193: Line 205:
 
         }
 
         }
 
     }
 
     }
}</code>
+
}
This class is pretty simple, but you can extend it as you want. Using is simple as well:
+
</code>
<code csharp>namespace IsolatedStorageSample
+
 
 +
You can extend this classes as you want (may be you want to save values only when application is shutting down?) or you can just copy this classes to your project and start working right now.
 +
Using {{Icode|IsolatedStorageProperty}} class is easier then {{Icode|IsolatedStorageSettings}}:
 +
 
 +
<code csharp>
 +
namespace IsolatedStorageSample
 
{
 
{
 
     using System.Windows;
 
     using System.Windows;
Line 201: Line 218:
 
     public partial class MainPage
 
     public partial class MainPage
 
     {
 
     {
 +
        //Setting declaration
 
         static readonly IsolatedStorageProperty<bool> SwitchProperty = new IsolatedStorageProperty<bool>("switch",true);
 
         static readonly IsolatedStorageProperty<bool> SwitchProperty = new IsolatedStorageProperty<bool>("switch",true);
 
          
 
          
Line 219: Line 237:
 
     }
 
     }
 
}</code>
 
}</code>
As you can see, a lot of lines of code are gone - very cool, when you store a lot of values.
+
We still have only one setting but a lot of lines are gone! - With ten or more property-settings this class become indispensable.
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
+
Lets create another setting - {{Icode|FirstRunTimeProperty}}:
in any time you want, like this:
+
 
<code csharp>using System;
+
<code csharp>
 +
using System;
  
 
namespace IsolatedStorageSample
 
namespace IsolatedStorageSample
Line 263: Line 282:
 
         }
 
         }
 
     }
 
     }
}</code>
+
}
FirstRunTimeProperty lets me know when was first application run.
+
</code>
<gallery>
+
File:IsolatedStorageRunTime.png|First Run Time
+
</gallery>
+
Every time you run the application message box shows only first time you run it.
+
  
<code csharp>namespace IsolatedStorageSample
+
{{Icode|FirstRunTimeProperty}} let us know when was first application run.
 +
 
 +
[[File:IsolatedStorageRunTime.png|200px|First Run Time]]
 +
 
 +
You can run the application two or more times to test it.
 +
 
 +
A good practice is to create a special static class, that would contain all your settings in it, so you can access any property in a program at any time:
 +
 
 +
<code csharp>
 +
namespace IsolatedStorageSample
 
{
 
{
 
     public static class SettingsContainer
 
     public static class SettingsContainer
Line 280: Line 304:
 
         //...
 
         //...
 
     }
 
     }
}</code>
+
}
''The "platform categories" will be displayed here in '''preview''' only - Copy paste relevant categories into text here''
+
</code>
 
+
{{VersionHint|Versions will be visible from this template when viewed in preview. You can delete this or leave it in the page as it is not displayed in final version}}
+
 
+
''Add categories below using category selector.''
+

Revision as of 12:22, 28 June 2013

This article explains how to use IsolatedStorageSettings and illustrates a helper class which enables using saving & retrieving (many) settings parameters easily.

WP Metro Icon File.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested withCompatibility
Platform(s): Windows Phone 7.5 and 8.0
Windows Phone 8
Windows Phone 7.5
Article
Keywords: IsolatedStorageSettings, Isolated Storage, User Settings
Created: jinek (09 Nov 2012)
Last edited: hamishwillee (28 Jun 2013)

Introduction

IsolatedStorageSettings is a dictionary for permanent storing values in Isolated Storage in the form of key-value pair. All that you have to do to store a value - is to provide a key for this value and a value itself.

You can store anything you want that is serializable, for example: user settings, layout information or application state. All settings from IsolatedStorageSettings are accessible after application shutdown and run again.

In this tutorial we will create a simple application that keeps one boolean value and then we are going to extend it for more convenient use.

Storing one setting with IsolatedStorageSettings

  1. Run Visual Studio 2012
  2. Create new Windows Phone project (7.1 or 8.0)
  3. Navigate to MainPage.xaml and replace all control 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>
  4. Navigate to MainPage.xaml.cs and insert code for storing and retrieving the value:
    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();
    }
    }
    }
    }
  5. Run the application
    As expected - the checkbox remembers last state before application shutdown.
    Simple setting

Why do I use thread synchronization? Because I do not know where else I will decide to call SaveSettings in the future, it could be ThreadPool, Timer callback or anything else. IsolatedStorageSettings is easy to use.

But if you are going to have more than just one setting-value - syncing, keeping key name, checking if setting exists and saving each time it has been updated may become a headache. Better way is to implement all this functionality in a helper class only once.

Helper class for easy storage of more setting values

Now we are going to create new class and implement logic for storing and retrieving setting values. With this, it should save the setting values every time we update it (in a thread safe manner), it should automatically set the default value if setting does not exist and finally it should keep the key name - we have to provide it only once at property declaration.

We create two new classes: IsolatedStoragePropertyHelper and IsolatedStorageProperty as illustrated below.

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;
}
}
}

You can extend this classes as you want (may be you want to save values only when application is shutting down?) or you can just copy this classes to your project and start working right now. Using IsolatedStorageProperty class is easier then IsolatedStorageSettings:

namespace IsolatedStorageSample
{
using System.Windows;
 
public partial class MainPage
{
//Setting declaration
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;
}
}
}

We still have only one setting but a lot of lines are gone! - With ten or more property-settings this class become indispensable.

Lets create another setting - FirstRunTimeProperty:

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 let us know when was first application run.

First Run Time

You can run the application two or more times to test it.

A good practice is to create a special static class, that would contain all your settings in it, so you can access any property in a program at any time:

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");
//...
}
}
481 page views in the last 30 days.
×