c # - подход для сохранения пользовательских настроек в приложении WPF? - PullRequest
64 голосов
/ 24 сентября 2010

Какой подход вы рекомендуете для сохранения пользовательских настроек в приложении WPF для Windows (на рабочем столе)?Обратите внимание, что идея заключается в том, что пользователь может изменить свои настройки во время выполнения, а затем закрыть приложение, после чего при последующем запуске приложения приложение будет использовать текущие настройки.По сути, тогда это будет выглядеть так, как будто настройки приложения не меняются.

Q1 - База данных или другой подход?У меня есть база данных sqlite, которую я буду использовать в любом случае, поэтому использование таблицы в базе данных будет таким же хорошим, как и любой другой подход?

Q2 - Если база данных: какой дизайн таблицы базы данных?Одна таблица со столбцами для разных типов данных, которые могут быть (например, string, long, DateTime и т. Д.) ИЛИ просто таблица со строкой для значения, по которому необходимо сериализовать и десериализовать значения?Я думаю, что первое было бы проще, и если настроек не так много, накладные расходы невелики?

Q3 - Можно ли для этого использовать настройки приложения?Если да, то есть ли какие-то особые задачи, необходимые для обеспечения постоянства здесь?Кроме того, что произойдет с использованием значения «по умолчанию» в конструкторе настроек приложения в этом случае?Будут ли значения по умолчанию переопределять какие-либо настройки, которые были сохранены между запуском приложения?(или вам не нужно использовать значение по умолчанию)

Ответы [ 9 ]

66 голосов
/ 24 сентября 2010

Вы можете использовать Настройки приложения , для этого использование базы данных - не лучший вариант, учитывая время, затраченное на чтение и запись настроек (особенно если вы используете веб-сервисы).

ЗдесьЕсть несколько ссылок, которые объясняют, как этого добиться и использовать их в WPF -

Настройки пользователя в WPF

Быстрый совет WPF: Как связать с приложением WPFресурсы и настройки?

Настраиваемое окно для WPF

12 голосов
/ 06 января 2012

Вы можете сохранить информацию о своих настройках как Strings XML в Settings.Default. Создайте несколько классов для хранения ваших данных конфигурации и убедитесь, что они [Serializable]. Затем с помощью следующих помощников вы можете сериализовать экземпляры этих объектов - или List<T> (или массивы T[] и т. Д.) Из них - до String. Храните каждую из этих различных строк в своем соответствующем слоте Settings.Default в Settings.

вашего приложения WPF.

Чтобы восстановить объекты при следующем запуске приложения, прочитайте Settings интересующую строку и Deserialize ожидаемый тип T (который на этот раз должен быть явно указан в качестве аргумента типа для Deserialize<T>) .

public static String Serialize<T>(T t)
{
    using (StringWriter sw = new StringWriter())
    using (XmlWriter xw = XmlWriter.Create(sw))
    {
        new XmlSerializer(typeof(T)).Serialize(xw, t);
        return sw.GetStringBuilder().ToString();
    }
}

public static T Deserialize<T>(String s_xml)
{
    using (XmlReader xw = XmlReader.Create(new StringReader(s_xml)))
        return (T)new XmlSerializer(typeof(T)).Deserialize(xw);
}
10 голосов
/ 10 октября 2013

Обновление : В настоящее время я бы использовал JSON.

Я также предпочитаю перейти с сериализацией к файлу. XML-файлы в основном соответствуют всем требованиям. Вы можете использовать встроенную ApplicationSettings, но у них есть некоторые ограничения и определенное, но (для меня) очень странное поведение, где они хранятся. Я использовал их много, и они работают. Но если вы хотите иметь полный контроль над тем, как и где они хранятся, я использую другой подход.

  1. Создайте класс Somewhere со всеми вашими настройками. Я назвал это MySettings
  2. Реализация Сохранить и прочитать для сохранения
  3. Используйте их в своем коде приложения

Преимущества:

  • Очень простой подход.
  • Один класс для настроек. Загрузка. Сохранить.
  • Все ваши настройки защищены.
  • Вы можете упростить или расширить логику в соответствии с вашими потребностями (управление версиями, множество профилей на пользователя и т. Д.)
  • В любом случае работает очень хорошо (база данных, WinForms, WPF, служба и т. Д ...)
  • Вы можете определить, где хранить файлы XML.
  • Вы можете найти их и манипулировать ими либо кодом, либо вручную
  • Он работает для любого метода развертывания, который я могу себе представить.

Недостатки: - Вы должны подумать о том, где хранить файлы настроек. (Но вы можете просто использовать вашу папку установки)

Вот простой пример (не тестировался) -

public class MySettings
{
    public string Setting1 { get; set; }
    public List<string> Setting2 { get; set; }

    public void Save(string filename)
    {
        using (StreamWriter sw = new StreamWriter(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            xmls.Serialize(sw, this);
        }
    }
    public MySettings Read(string filename)
    {
        using (StreamReader sw = new StreamReader(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            return xmls.Deserialize(sw) as MySettings;
        }
    }
}

А вот как это использовать. Можно загрузить значения по умолчанию или переопределить их настройками пользователя, просто проверив, существуют ли пользовательские настройки:

public class MyApplicationLogic
{
    public const string UserSettingsFilename = "settings.xml";
    public string _DefaultSettingspath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\" + UserSettingsFilename;

    public string _UserSettingsPath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\UserSettings\\" + 
        UserSettingsFilename;

    public MyApplicationLogic()
    {
        // if default settings exist
        if (File.Exists(_UserSettingsPath))
            this.Settings = Settings.Read(_UserSettingsPath);
        else
            this.Settings = Settings.Read(_DefaultSettingspath);
    }
    public MySettings Settings { get; private set; }

    public void SaveUserSettings()
    {
        Settings.Save(_UserSettingsPath);
    }
}

может быть, кто-то вдохновился этим подходом. Вот как я это делаю сейчас на протяжении многих лет, и я очень доволен этим.

6 голосов
/ 24 сентября 2010

Наиболее типичным подходом к этому вопросу является долгосрочный: изолированное хранилище.

Сериализация состояния управления в XML или другом формате (особенно легко, если вы сохраняете свойства зависимостей в WPF), затем сохраните файл в изолированном хранилище пользователя.

Если вы действительно хотите пойти по пути настройки приложения, я сам попробовал нечто подобное в одном месте ... хотя приведенный ниже подход можно легко адаптировать для использования изолированного хранилища:

class SettingsManager
{
    public static void LoadSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            try
            {
                element.SetValue(savedElements[element], Properties.Settings.Default[sender.Name + "." + element.Name]);
            }
            catch (Exception ex) { }
        }
    }

    public static void SaveSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            Properties.Settings.Default[sender.Name + "." + element.Name] = element.GetValue(savedElements[element]);
        }
        Properties.Settings.Default.Save();
    }

    public static void EnsureProperties(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        foreach (FrameworkElement element in savedElements.Keys)
        {
            bool hasProperty =
                Properties.Settings.Default.Properties[sender.Name + "." + element.Name] != null;

            if (!hasProperty)
            {
                SettingsAttributeDictionary attributes = new SettingsAttributeDictionary();
                UserScopedSettingAttribute attribute = new UserScopedSettingAttribute();
                attributes.Add(attribute.GetType(), attribute);

                SettingsProperty property = new SettingsProperty(sender.Name + "." + element.Name,
                    savedElements[element].DefaultMetadata.DefaultValue.GetType(), Properties.Settings.Default.Providers["LocalFileSettingsProvider"], false, null, SettingsSerializeAs.String, attributes, true, true);
                Properties.Settings.Default.Properties.Add(property);
            }
        }
        Properties.Settings.Default.Reload();
    }
}

..... и ....

  Dictionary<FrameworkElement, DependencyProperty> savedElements = new Dictionary<FrameworkElement, DependencyProperty>();

public Window_Load(object sender, EventArgs e) {
           savedElements.Add(firstNameText, TextBox.TextProperty);
                savedElements.Add(lastNameText, TextBox.TextProperty);

            SettingsManager.LoadSettings(this, savedElements);
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            SettingsManager.SaveSettings(this, savedElements);
        }
4 голосов
/ 24 сентября 2010

Помимо базы данных, вы также можете иметь следующие опции для сохранения пользовательских настроек

  1. в разделе HKEY_CURRENT_USER

  2. вфайл в папке AppData

  3. с использованием файла Settings в WPF и установкой его области действия как Пользователь

3 голосов
/ 14 декабря 2011

По моему опыту, сохранение всех настроек в таблице базы данных - лучшее решение. Даже не беспокойтесь о производительности. Современные базы данных быстры и могут легко хранить тысячи столбцов в таблице. Я усвоил этот трудный путь - до того, как начал сериализовать / десериализовать - кошмар. Хранение его в локальном файле или реестре имеет одну большую проблему - если вам нужно поддерживать ваше приложение и компьютер выключен - пользователь не перед ним - вы ничего не можете сделать .... если настройки находятся в БД - вы можете поменял их и альт не говоря уже о том, что можно сравнить настройки ....

1 голос
/ 24 сентября 2010

Обычно я делаю такие вещи, определяя пользовательский класс настроек [Serializable] и просто сериализуя его на диск.В вашем случае вы можете так же легко сохранить его как строковый блоб в вашей базе данных SQLite.

0 голосов
/ 21 февраля 2016

Я хотел использовать управляющий файл xml на основе класса для моего настольного WPF-приложения VB.net. Приведенный выше код, чтобы сделать все это в одном, отлично и направил меня в правильном направлении. Если кто-то ищет решение VB.net, вот класс, который я построил:

Imports System.IO
Imports System.Xml.Serialization

Public Class XControl

Private _person_ID As Integer
Private _person_UID As Guid

'load from file
Public Function XCRead(filename As String) As XControl
    Using sr As StreamReader = New StreamReader(filename)
        Dim xmls As New XmlSerializer(GetType(XControl))
        Return CType(xmls.Deserialize(sr), XControl)
    End Using
End Function

'save to file
Public Sub XCSave(filename As String)
    Using sw As StreamWriter = New StreamWriter(filename)
        Dim xmls As New XmlSerializer(GetType(XControl))
        xmls.Serialize(sw, Me)
    End Using
End Sub

'all the get/set is below here

Public Property Person_ID() As Integer
    Get
        Return _person_ID
    End Get
    Set(value As Integer)
        _person_ID = value
    End Set
End Property

Public Property Person_UID As Guid
    Get
        Return _person_UID
    End Get
    Set(value As Guid)
        _person_UID = value
    End Set
End Property

End Class
0 голосов
/ 18 сентября 2013
  1. Во всех местах, где я работал, база данных была обязательной из-за поддержки приложений.Как сказал Адам, пользователь может не находиться за своим рабочим столом, или компьютер может быть выключен, или вы можете быстро изменить чью-либо конфигурацию или назначить новичку конфигурацию по умолчанию (или члена команды).1005 *

    Если настройки могут увеличиться по мере выпуска новых версий приложения, вы можете сохранить данные в виде больших двоичных объектов, которые затем могут быть десериализованы приложением.Это особенно полезно, если вы используете что-то вроде Prism, которое обнаруживает модули, так как вы не можете знать, какие настройки вернет модуль.Блобы могут быть введены с помощью комбинированного ключа «имя пользователя / машина».Таким образом, вы можете иметь разные настройки для каждой машины.

  2. Я не слишком много использовал встроенный класс «Настройки», поэтому воздержусь от комментариев.:)

...