c# - подход для сохранения пользовательских настроек в приложении WPF?

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

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

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

Q3-Смогл Настройки приложения будут использоваться для этого? Если да, то есть ли какие-либо специальные задачи, необходимые для обеспечения сохраняемости здесь? Также что произойдет с использованием значения "по умолчанию" в конструкторе настроек приложения в этом случае? Будет ли значение по умолчанию переопределять любые параметры, сохраненные между запуском приложения? (или вам не нужно использовать значение по умолчанию)

9 ответов


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

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

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

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

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


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

чтобы восстановить объекты при следующем запуске приложения, прочитайте 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);
}

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

  1. создать класс, где все ваши настройки. Я назвал его MySettings
  2. реализовать сохранение и Чтение для настойчивость
  3. используйте их в вас application-code

плюсы:

  • очень простой подход.
  • один класс для настроек. Нагрузка. Спасать.
  • все ваши настройки типа safe.
  • вы можете упростить или расширить логику для ваших нужд (управление версиями, много профилей на пользователя и т. д.)
  • он работает очень хорошо в любом случае (база данных, 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);
    }
}

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


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

Сериализуйте состояние элемента управления в 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);
        }

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

  1. реестр в разделе HKEY_CURRENT_USER

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

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


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


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


  1. во всех местах, где я работал, база данных была обязательной, потому что поддержки приложения. Как сказал Адам, пользователь может не быть за своим столом или машина может быть выключена, или вы можете быстро изменить чью-то конфигурацию или назначить новому столяру конфигурацию по умолчанию (или члена команды).

  2. Если настройки, вероятно, будут расти по мере выпуска новых версий приложения, вы можете сохранить данные в виде blobs, которые затем могут быть десериализовано приложением. Это особенно полезно, если вы используете что-то вроде Prism, который обнаруживает модули, так как вы не можете знать, какие настройки модуль вернет. Капли могут быть введены составным ключом username/machine. Таким образом, вы можете иметь разные настройки для каждой машины.

  3. Я не использовал встроенный класс настроек, поэтому я воздержусь от комментариев. :)


Я хотел использовать файл управления xml на основе класса для моего VB.net настольное приложение WPF. Приведенный выше код, чтобы сделать это все в один прекрасный и поставил меня в правильном направлении. В случае, если кто-то ищет 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