Статьи

Windows Phone: как легко хранить настройки пользователя

Вот базовый класс для приложений Windows Phone, который я использовал для хранения пользовательских настроек. Он включает в себя IsolatedStorageSettings и представляет собой слегка модифицированную версию класса SettingsStore, включенную в «Учебный пример для создания расширенных приложений Windows Phone — примеры кода» . Вот пример того, как использовать базовый класс (в приложении Windows Phone 8):

public class MySettingsStore : SettingsStore
{
    public bool IsFirstAppStart
    {
        get { return this.GetValueOrDefault(true); }
        set { this.AddOrUpdateValue(value); }
    }
 
    public string FirstName
    {
        get { return this.GetValueOrDefault(""); }
        set { this.AddOrUpdateValue(value); }
    }
}

Класс может использоваться для хранения более сложных объектов, если они сериализуемы:

[DataContract]
public class User
{
    [DataMember]
    public string Name { get; set; }
}
 
public class MySettingsStore : SettingsStore
{
    public List<User> Users
    {
        get { return this.GetValueOrDefault(new List<User>()); }
        set { this.AddOrUpdateValue(value); }
    }
}

Метод GetValueOrDefault принимает один параметр, и это значение по умолчанию, которое возвращается, если не найдено сохраненных настроек.

В вашем приложении вы можете сохранить настройки, используя следующий код:

var settingsStore = new MySettingsStore();
...
settingsStore.FirstName = this.FirstNameTextBox.Text;

И чтобы прочитать настройку (или значение по умолчанию):

var settingsStore = new MySettingsStore();
...
this.FirstNameTextBox.Text = settingsStore.FirstName;

Вот полный код для базового класса SettingsStore. Он использует CallerMemberName, чтобы автоматически вычесть ключ для настройки.

using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Runtime.CompilerServices;
 
namespace Adafy.Infra
{
    public class SettingsStore
    {
        private readonly IsolatedStorageSettings isolatedStore;
 
        public SettingsStore()
        {
            this.isolatedStore = IsolatedStorageSettings.ApplicationSettings;
        }
 
        protected void AddOrUpdateValue(object value, [CallerMemberName]string key = "key")
        {
            var valueChanged = false;
 
            lock (this)
            {
 
                try
                {
                    if (value == null)
                    {
                        // Nothing to remove
                        if (!this.isolatedStore.Contains(key))
                            return;
 
                        this.isolatedStore.Remove(key);
                        this.Save();
                    }
 
                    // If the new value is different, set the new value.
                    if (this.isolatedStore[key] != value)
                    {
                        this.isolatedStore[key] = value;
                        valueChanged = true;
                    }
                }
                catch (KeyNotFoundException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
                catch (ArgumentException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
 
                if (valueChanged)
                {
                    this.Save();
                }
            }
        }
 
        protected T GetValueOrDefault<T>(T defaultValue, [CallerMemberName]string key = "key")
        {
            lock (this)
            {
 
                T value;
 
                try
                {
                    value = (T)this.isolatedStore[key];
                }
                catch (KeyNotFoundException)
                {
                    value = defaultValue;
                }
                catch (ArgumentException)
                {
                    value = defaultValue;
                }
 
                return value;
            }
 
        }
 
        private void Save()
        {
            try
            {
                this.isolatedStore.Save();
            }
            catch (Exception)
            {
                return;
            }
        }
    }
 
}

Настройки Store для Windows Phone 7

CallerMemberName недоступно в Windows Phone 7. По этой причине в каждой настройке должен быть указан уникальный ключ:

public class MySettingsStore : SettingsStore
{
    private const string FirstAppStartKey = "MyKey";
    private const string FirstNameKey = "MyKey2";
 
    public bool IsFirstAppStart
    {
        get { return this.GetValueOrDefault(true, FirstAppStartKey); }
        set { this.AddOrUpdateValue(value, FirstAppStartKey); }
    }
 
    public string FirstName
    {
        get { return this.GetValueOrDefault("", FirstNameKey); }
        set { this.AddOrUpdateValue(value, FirstNameKey); }
    }
}

Вот полный код WP7-версии SettingsStore, который практически идентичен тому, который представлен в Prism.

using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Runtime.CompilerServices;
 
namespace Adafy.Infra
{
    public class SettingsStore
    {
        private readonly IsolatedStorageSettings isolatedStore;
 
        public SettingsStore()
        {
            this.isolatedStore = IsolatedStorageSettings.ApplicationSettings;
        }
 
        protected void AddOrUpdateValue(object value, [CallerMemberName]string key = "key")
        {
            var valueChanged = false;
 
            lock (this)
            {
 
                try
                {
                    if (value == null)
                    {
                        // Nothing to remove
                        if (!this.isolatedStore.Contains(key))
                            return;
 
                        this.isolatedStore.Remove(key);
                        this.Save();
                    }
 
                    // If the new value is different, set the new value.
                    if (this.isolatedStore[key] != value)
                    {
                        this.isolatedStore[key] = value;
                        valueChanged = true;
                    }
                }
                catch (KeyNotFoundException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
                catch (ArgumentException)
                {
                    this.isolatedStore.Add(key, value);
                    valueChanged = true;
                }
 
                if (valueChanged)
                {
                    this.Save();
                }
            }
        }
 
        protected T GetValueOrDefault<T>(T defaultValue, [CallerMemberName]string key = "key")
        {
            lock (this)
            {
 
                T value;
 
                try
                {
                    value = (T)this.isolatedStore[key];
                }
                catch (KeyNotFoundException)
                {
                    value = defaultValue;
                }
                catch (ArgumentException)
                {
                    value = defaultValue;
                }
 
                return value;
            }
 
        }
 
        private void Save()
        {
            try
            {
                this.isolatedStore.Save();
            }
            catch (Exception)
            {
                return;
            }
        }
    }
}

Классы SettingsStore можно комбинировать с помощью условной компиляции.