用于保存WPF应用程序中的用户设置的方法?
你推荐什么方法在WPF窗口(桌面)应用程序中保持用户设置? 请注意,这个想法是,用户可以在运行时更改设置,然后closures应用程序,然后在启动应用程序后,应用程序将使用当前设置。 有效的话,它会显示好像应用程序设置不会改变。
Q1 – 数据库还是其他方法? 我有一个SQLite数据库,我将无论如何使用,因此使用数据库中的表将是一样好任何方法?
Q2 – 如果数据库:什么数据库表devise? 一个表有不同数据types的列(例如string
, long
, DateTime
等),或者只是一个表格,其中的值必须是序列化和反序列化的值。 我想第一个会更容易,如果没有太多的设置,开销不大?
Q3 – 可以使用应用程序设置吗? 如果有的话,还有什么特别的任务需要在这里实现持久性? 在这种情况下,在应用程序设置devise器中重新使用“默认”值会发生什么情况? 默认会覆盖在运行应用程序之间保存的任何设置吗? (或者你是否需要不使用默认值)
您可以使用应用程序设置为此,考虑到读取和写入设置所花费的时间(特别是如果您使用Web服务)使用数据库不是最佳选项。
这里有几个链接,说明如何实现这一点,并在WPF中使用它们 –
在WPF中的用户设置
快速WPF提示:如何绑定到WPF应用程序资源和设置?
一个WPF的可configuration窗口
您可以将设置信息作为Strings
存储在Settings.Default
。 创build一些类来存储configuration数据,并确保它们是[Serializable]
。 然后,通过以下帮助程序,可以将这些对象的实例 – 或者List<T>
(或数组T[]
等) – 序列化为String
。 将这些不同的string中的每一个都存储在您自己的WPF应用程序Settings
Settings.Default
插槽中。
要在下一次应用程序启动时恢复对象,请阅读感兴趣的Settings
string,并Deserialize
化为预期的typesT
(此时必须明确指定为Deserialize<T>
的types参数)。
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
内置,但这些有一些限制和定义,但(对我来说)非常奇怪的行为,他们存储。 我用了很多,他们工作。 但是,如果你想完全控制他们存储的方式和位置,我使用另一种方法。
- 用你所有的设置在某个地方做一个课。 我把它命名为
MySettings
- 实施保存并读取持久性
- 在你的应用程序代码中使用它们
优点:
- 非常简单的方法。
- 一类设置。 加载。 保存。
- 所有的设置都是安全的。
- 您可以根据需要简化或扩展逻辑(版本控制,每个用户的许多configuration文件等)
- 它在任何情况下工作得很好(数据库,WinForms,WPF,服务等…)
- 您可以定义在哪里存储XML文件。
- 你可以find他们,并通过代码或手动操纵他们
- 它适用于我能想象的任何部署方法。
缺点: – 你必须考虑在哪里存储你的设置文件。 (但是你可以使用你的安装文件夹)
这是一个简单的例子(未testing)。
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); }
除了数据库,还可以有以下选项来保存用户相关的设置
-
registry下的
HKEY_CURRENT_USER
-
在
AppData
文件夹中的文件中 -
使用WPF中的
Settings
文件,并将其范围设置为用户
根据我的经验,将所有设置存储在数据库表中是最好的解决scheme。 甚至不担心performance。 今天的数据库很快,可以很容易地在一个表中存储数千列。 我在艰难的阶段学到了这一点 – 在我进行了serilizing / deserializing之前 – 恶梦。 将其存储在本地文件或registry中有一个大问题 – 如果您必须支持您的应用程序,并且计算机处于closures状态 – 用户不在其前面 – 则无法执行任何操作….如果数据库位于数据库中,则可以改变他们和中提琴不提,你可以比较的设置….
我通常通过定义一个自定义的[ Serializable
]设置类并简单地将其序列化到磁盘来做这种事情。 在你的情况下,你可以轻松地将它作为一个stringblob存储在你的SQLite数据库中。
-
在我工作的所有地方,由于应用程序的支持,数据库是强制性的。 正如亚当所说,用户可能不在他的办公桌或机器可能closures,或者您可能想要快速更改某人的configuration或指定一个新的joiner默认(或团队成员)的configuration。
-
如果这些设置可能随着应用程序的新版本的发布而增长,那么您可能希望将数据存储为blob,然后由应用程序对其进行反序列化。 如果你使用类似棱镜的东西来发现模块,这是非常有用的,因为你不知道模块将返回什么样的设置。 blob可以通过用户名/机器组合键来键入。 这样你可以为每台机器设置不同的设置。
-
我没有使用内置的Settings类很多,所以我会放弃评论。 🙂
我想为我的VB.net桌面WPF应用程序使用基于类的xml控制文件。 上面的代码在一个这样做是很好的,并在正确的方向。 如果有人正在寻找一个VB.net解决scheme,这里是我build立的类:
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