Welchen Ansatz empfehlen Sie, um Benutzereinstellungen in einer WPF-Windows-Anwendung (Desktop) beizubehalten? Beachten Sie, dass der Benutzer seine Einstellungen zur Laufzeit ändern und dann die Anwendung schließen kann. Wenn die Anwendung später gestartet wird, verwendet die Anwendung die aktuellen Einstellungen. Tatsächlich sieht es dann so aus, als würden sich die Anwendungseinstellungen nicht ändern.
Q1 - Datenbank oder anderer Ansatz? Ich habe eine SQLite-Datenbank, die ich sowieso verwenden werde, daher wäre die Verwendung einer Tabelle in der Datenbank so gut wie jeder Ansatz?
F2 - Wenn Datenbank: Welches Datenbanktabellendesign? Eine Tabelle mit Spalten für verschiedene Datentypen , die man haben könnte (zB string
, long
, DateTime
usw.) oder nur eine Tabelle mit einem String für den Wert , auf das Sie serialisiert haben und de-serialize der Werte? Ich denke, das erste wäre einfacher, und wenn es nicht viele Einstellungen gibt, ist der Overhead nicht viel?
F3 - Könnten hierfür Anwendungseinstellungen verwendet werden? Wenn ja, sind spezielle Aufgaben erforderlich, um die Persistenz hier zu ermöglichen? Was würde in diesem Fall auch in Bezug auf die Verwendung des "Standard" -Werts im Anwendungseinstellungen-Designer passieren? Würde die Standardeinstellung alle Einstellungen überschreiben, die zwischen dem Ausführen der Anwendung gespeichert wurden? (oder müssten Sie NICHT den Standardwert verwenden)
Antworten:
Sie können hierfür die Anwendungseinstellungen verwenden . Die Verwendung der Datenbank ist angesichts der Zeit, die zum Lesen und Schreiben der Einstellungen benötigt wird, nicht die beste Option (insbesondere, wenn Sie Webdienste verwenden).
Hier sind einige Links, die erklären, wie dies erreicht und in WPF verwendet werden kann -
Benutzereinstellungen in WPF
Schneller WPF-Tipp: Wie binde ich mich an WPF-Anwendungsressourcen und -einstellungen?
Ein konfigurierbares Fenster für WPF
quelle
Aktualisieren : Heutzutage würde ich JSON verwenden.
Ich bevorzuge es auch, mit der Serialisierung in die Datei zu gehen. XML-Dateien erfüllen fast alle Anforderungen. Sie können das
ApplicationSettings
Build-In verwenden, aber diese haben einige Einschränkungen und ein definiertes, aber (für mich) sehr seltsames Verhalten, in dem sie gespeichert sind. Ich habe sie oft benutzt und sie funktionieren. Aber wenn Sie die volle Kontrolle darüber haben möchten, wie und wo sie gespeichert wurden, verwende ich einen anderen Ansatz.MySettings
Vorteile:
Nachteile: - Sie müssen überlegen, wo Sie Ihre Einstellungsdateien speichern sollen. (Sie können aber einfach Ihren Installationsordner verwenden)
Hier ist ein einfaches Beispiel (nicht getestet) -
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; } } }
Und hier ist, wie man es benutzt. Es ist möglich, Standardwerte zu laden oder sie mit den Benutzereinstellungen zu überschreiben, indem Sie nur überprüfen, ob Benutzereinstellungen vorhanden sind:
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); } }
Vielleicht lässt sich jemand von diesem Ansatz inspirieren. So mache ich das jetzt seit vielen Jahren und ich bin ziemlich zufrieden damit.
quelle
Sie können Ihre Einstellungsinformationen ab
Strings
XML in der speichernSettings.Default
. Erstellen Sie einige Klassen, um Ihre Konfigurationsdaten zu speichern und sicherzustellen, dass dies der Fall ist[Serializable]
. Mit den folgenden Hilfsprogrammen können Sie dann Instanzen dieser Objekte - oderList<T>
(oder ArraysT[]
usw.) davon - serialisierenString
. Speichern Sie jede dieser verschiedenen Zeichenfolgen in einem eigenenSettings.Default
Steckplatz in Ihrer WPF-AnwendungSettings
.Um die Objekte beim nächsten Start der App wiederherzustellen, lesen Sie die gewünschte
Settings
Zeichenfolge undDeserialize
den erwarteten TypT
(für den diesmal explizit als Typargument angegeben werden mussDeserialize<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); }
quelle
Der langfristig typischste Ansatz für diese Frage lautet: Isolierter Speicher.
Serialisieren Sie Ihren Steuerungsstatus in XML oder ein anderes Format (besonders einfach, wenn Sie Abhängigkeitseigenschaften mit WPF speichern) und speichern Sie die Datei dann im isolierten Speicher des Benutzers.
Wenn Sie die App-Einstellungsroute einschlagen möchten, habe ich an einer Stelle selbst etwas Ähnliches versucht ... obwohl der folgende Ansatz leicht für die Verwendung von isoliertem Speicher angepasst werden könnte:
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(); } }
.....und....
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); }
quelle
Neben einer Datenbank können Sie auch folgende Optionen zum Speichern benutzerbezogener Einstellungen verwenden
Registrierung unter
HKEY_CURRENT_USER
in einer Datei im
AppData
OrdnerVerwenden der
Settings
Datei in WPF und Festlegen des Bereichs als Benutzerquelle
Nach meiner Erfahrung ist das Speichern aller Einstellungen in einer Datenbanktabelle die beste Lösung. Mach dir keine Sorgen um die Leistung. Die heutigen Datenbanken sind schnell und können problemlos Tausende von Spalten in einer Tabelle speichern. Ich habe das auf die harte Tour gelernt - bevor ich den Albtraum serilisierte / deserialisierte -. Das Speichern in einer lokalen Datei oder Registrierung hat ein großes Problem: Wenn Sie Ihre App unterstützen müssen und der Computer ausgeschaltet ist, ist der Benutzer nicht davor. Sie können nichts tun. Wenn sich die Einstellungen in der Datenbank befinden, können Sie dies geändert sie und Bratsche nicht zu erwähnen, dass Sie die Einstellungen vergleichen können ....
quelle
Normalerweise mache ich so etwas, indem ich eine benutzerdefinierte [
Serializable
] Einstellungsklasse definiere und sie einfach auf die Festplatte serialisiere. In Ihrem Fall können Sie es genauso einfach wie einen String-Blob in Ihrer SQLite-Datenbank speichern.quelle
An allen Orten, an denen ich gearbeitet habe, war die Datenbank aufgrund der Anwendungsunterstützung obligatorisch. Wie Adam sagte, ist der Benutzer möglicherweise nicht an seinem Schreibtisch oder der Computer ist ausgeschaltet, oder Sie möchten schnell die Konfiguration einer anderen Person ändern oder einem neuen Joiner eine Standardkonfiguration (oder die Konfiguration eines Teammitglieds) zuweisen.
Wenn die Einstellungen wahrscheinlich zunehmen, wenn neue Versionen der Anwendung veröffentlicht werden, möchten Sie die Daten möglicherweise als Blobs speichern, die dann von der Anwendung deserialisiert werden können. Dies ist besonders nützlich, wenn Sie Prism verwenden, das Module erkennt, da Sie nicht wissen können, welche Einstellungen ein Modul zurückgeben wird. Die Blobs können über den zusammengesetzten Benutzernamen / Maschinenschlüssel eingegeben werden. Auf diese Weise können Sie für jede Maschine unterschiedliche Einstellungen vornehmen.
Ich habe die eingebaute Klasse "Einstellungen" nicht viel verwendet, daher verzichte ich auf Kommentare. :) :)
quelle
Ich wollte eine XML-Steuerdatei basierend auf einer Klasse für meine VB.net-Desktop-WPF-Anwendung verwenden. Der obige Code, um dies alles in einem zu tun, ist ausgezeichnet und bringt mich in die richtige Richtung. Für den Fall, dass jemand nach einer VB.net-Lösung sucht, ist hier die Klasse, die ich erstellt habe:
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
quelle