[英]C# - approach for saving user settings in a WPF application?
對於在 WPF windows(桌面)應用程序中持久保存用戶設置,您推薦什么方法? 請注意,這個想法是用戶可以在運行時更改他們的設置,然后可以關閉應用程序,然后在稍后啟動應用程序時應用程序將使用當前設置。 實際上,應用程序設置似乎沒有更改。
Q1 - 數據庫或其他方法? 我確實有一個 sqlite 數據庫,無論如何我都會使用它,因此在數據庫中使用一個表會和任何方法一樣好嗎?
Q2 - 如果數據庫:什么數據庫表設計? 一個包含不同數據類型的列的表(例如string
、 long
、 DateTime
等),或者只是一個包含字符串的表,您必須根據該字符串對值進行序列化和反序列化? 我認為第一個會更容易,如果設置不多,開銷也不大?
Q3 - 應用程序設置可以用於此嗎? 如果是這樣,是否需要執行任何特殊任務才能在此處啟用持久性? 此外,在這種情況下,在應用程序設置設計器中使用“默認”值會發生什么情況? 默認值是否會覆蓋在運行應用程序之間保存的任何設置? (或者您是否需要不使用默認值)
您可以為此使用應用程序設置,考慮到讀取和寫入設置所花費的時間(特別是如果您使用 Web 服務),使用數據庫並不是最佳選擇。
這里有幾個鏈接解釋了如何實現這一點並在 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);
}
}
也許有人會受到這種方法的啟發。 這就是我多年來一直這樣做的方式,我對此感到非常滿意。
您可以將設置信息作為 XML Strings
存儲在Settings.Default
。 創建一些類來存儲您的配置數據並確保它們是[Serializable]
。 然后,使用以下幫助程序,您可以將這些對象的實例(或它們的List<T>
(或數組T[]
等)序列化為String
。 將這些不同的字符串中的每一個存儲在 WPF 應用程序的Settings
各自的Settings.Default
插槽中。
要在應用程序下次啟動時恢復對象,請讀取感興趣的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
下的HKEY_CURRENT_USER
在AppData
文件夾中的文件中
在 WPF 中使用Settings
文件並將其范圍設置為用戶
根據我的經驗,將所有設置存儲在數據庫表中是最好的解決方案。 甚至不用擔心性能。 今天的數據庫速度很快,可以輕松地在一個表中存儲數千列。 在我進行序列化/反序列化之前,我通過艱難的方式學到了這一點——噩夢。 將它存儲在本地文件或注冊表中有一個大問題 - 如果您必須支持您的應用程序並且計算機已關閉 - 用戶不在它面前 - 您無能為力.... 如果設置在 DB 中 - 您可以更改了它們和中提琴,更不用說您可以比較設置....
您可以使用 SQLite,一個小型、快速、獨立、功能齊全的 SQL 數據庫引擎。 在嘗試設置文件和 XML 文件方法后,我個人推薦它。
安裝NuGet package SYSTEM.DATA.SQLite它是88393605555588提供商SQLite的提供程序。
1.安裝 SQLite 2.創建數據庫文件 3.創建表以保存設置 4.訪問應用程序中的數據庫文件以讀取和編輯設置。
我覺得這種方法對應用程序設置非常有幫助,因為我可以對數據庫進行調整,還可以利用 ADO.Net 和 LINQ 功能
我通常通過定義自定義 [ Serializable
] 設置類並將其序列化到磁盤來完成此類操作。 在您的情況下,您可以像將字符串 blob 一樣輕松地存儲在 SQLite 數據庫中。
在我工作過的所有地方,由於應用程序支持,數據庫一直是強制性的。 正如 Adam 所說,用戶可能不在他的辦公桌前或機器可能關閉,或者您可能想要快速更改某人的配置或為新加入者分配默認(或團隊成員)配置。
如果設置可能會隨着應用程序新版本的發布而增加,您可能希望將數據存儲為 blob,然后應用程序可以反序列化這些數據。 如果您使用諸如發現模塊的 Prism 之類的東西,這將特別有用,因為您無法知道模塊將返回哪些設置。 blob 可以通過用戶名/機器組合鍵進行鍵控。 這樣您就可以為每台機器設置不同的設置。
我很少使用內置的 Settings 類,所以我將避免發表評論。 :)
我想為我的 VB.net 桌面 WPF 應用程序使用基於類的 xml 控制文件。 上面的代碼合二為一地完成了這一切,它讓我朝着正確的方向前進。 如果有人正在尋找 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.