Какой подход вы рекомендуете для сохранения пользовательских настроек в приложении WPF для Windows (для настольных ПК)? Обратите внимание, что идея состоит в том, что пользователь может изменить свои настройки во время выполнения, а затем может закрыть приложение, а затем при запуске приложения позже приложение будет использовать текущие настройки. Фактически тогда это будет выглядеть так, как будто настройки приложения не меняются.
Q1 - База данных или другой подход? У меня есть база данных sqlite, которую я буду использовать в любом случае, поэтому использование таблицы в базе данных было бы так же хорошо, как и любой другой подход?
Q2 - Если база данных: какой дизайн таблицы базы данных? Одна таблица со столбцами для разных типов данных, которые могут быть (например string
, long
и DateTime
т. Д.) ИЛИ просто таблица со строкой для значения, по которому вам нужно сериализовать и десериализовать значения? Думаю, первое было бы проще, а если настроек не так много, накладных расходов не так много?
Q3 - Могут ли для этого использоваться настройки приложения? Если да, то требуются ли какие-то особые задачи для включения персистентности? И что в этом случае произойдет с использованием значения «по умолчанию» в конструкторе параметров приложения? Будет ли значение по умолчанию отменять любые настройки, которые были сохранены между запуском приложения? (или вам НЕ нужно использовать значение по умолчанию)
Ответы:
Для этого вы можете использовать настройки приложения , использование базы данных - не лучший вариант, учитывая время, затрачиваемое на чтение и запись настроек (особенно если вы используете веб-службы).
Вот несколько ссылок, которые объясняют, как этого добиться и использовать их в WPF:
Настройки пользователя в WPF
Быстрый совет по WPF: как выполнить привязку к ресурсам и настройкам приложения WPF?
Настраиваемое окно для WPF
источник
Обновление : в настоящее время я бы использовал JSON.
Я также предпочитаю использовать сериализацию в файл. Файлы XML удовлетворяют практически всем требованиям. Вы можете использовать эту
ApplicationSettings
сборку, но у них есть некоторые ограничения и определенное, но (для меня) очень странное поведение, где они хранятся. Я их много использовал, и они работают. Но если вы хотите полностью контролировать, как и где они хранятся, я использую другой подход.MySettings
Преимущества:
Недостатки: - Вы должны думать, где хранить файлы настроек. (Но вы можете просто использовать свою установочную папку)
Вот простой пример (не проверенный) -
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); } }
может быть, кого-то вдохновит такой подход. Я так делаю уже много лет, и меня это вполне устраивает.
источник
Вы можете сохранить информацию о своих настройках в
Strings
формате XML в форматеSettings.Default
. Создайте несколько классов для хранения данных конфигурации и убедитесь, что они есть[Serializable]
. Затем с помощью следующих помощников вы можете сериализовать экземпляры этих объектов - илиList<T>
(или массивыT[]
и т. Д.) Из них - вString
. Сохраните каждую из этих различных строк в соответствующемSettings.Default
слоте в вашем приложении WPFSettings
.Чтобы восстановить объекты при следующем запуске приложения, прочитайте
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 или другом формате (особенно легко, если вы сохраняете свойства зависимостей с помощью 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); }
источник
Помимо базы данных, вы также можете иметь следующие параметры для сохранения настроек, связанных с пользователем
реестр под
HKEY_CURRENT_USER
в файле в
AppData
папкеиспользуя
Settings
файл в WPF и установив его область действия как Пользовательисточник
По моему опыту, лучшим решением является сохранение всех настроек в таблице базы данных. Даже не беспокойтесь о производительности. Современные базы данных работают быстро и легко могут хранить тысячи столбцов в таблице. Я усвоил это на собственном горьком опыте - до того, как я начал сериализацию / десериализацию - кошмар. Хранение его в локальном файле или реестре имеет одну большую проблему - если вам нужно поддерживать свое приложение, а компьютер выключен - пользователь не находится перед ним - вы ничего не можете сделать .... если настройки находятся в БД - вы можете поменял их и альт, не говоря уже о том, что можно сравнить настройки ....
источник
Обычно я делаю такие вещи, определяя собственный
Serializable
класс настроек [ ] и просто сериализуя его на диск. В вашем случае вы могли бы так же легко сохранить его как строковый blob в своей базе данных SQLite.источник
Во всех местах, где я работал, база данных была обязательной из-за поддержки приложений. Как сказал Адам, пользователь может не находиться за своим столом, или машина может быть выключена, или вы можете быстро изменить чью-то конфигурацию или назначить новому участнику конфигурацию по умолчанию (или конфигурацию члена команды).
Если параметры, вероятно, будут расти по мере выпуска новых версий приложения, вы можете захотеть сохранить данные в виде больших двоичных объектов, которые затем могут быть десериализованы приложением. Это особенно полезно, если вы используете что-то вроде Prism, которое обнаруживает модули, поскольку вы не можете знать, какие настройки вернет модуль. Для больших двоичных объектов можно использовать составной ключ имени пользователя и компьютера. Таким образом, у вас могут быть разные настройки для каждой машины.
Я не особо использовал встроенный класс настроек, поэтому воздержусь от комментариев. :)
источник
Я хотел использовать файл управления 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
источник