it-swarm.com.de

c # - Ansatz zum Speichern von Benutzereinstellungen in einer WPF-Anwendung?

Welchen Ansatz empfehlen Sie, um Benutzereinstellungen in einer WPF-Windows-Anwendung (Desktop-Anwendung) beizubehalten? Die Idee ist, 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. Es erscheint dann so, als würden sich die Anwendungseinstellungen nicht ändern. 

Q1 - Datenbank oder anderer Ansatz? Ich habe eine sqlite-Datenbank, die ich trotzdem verwenden werde. Daher wäre die Verwendung einer Tabelle in der Datenbank so gut wie jeder Ansatz.

F2 - Wenn Datenbank: Welches Datenbanktabellen-Design? Eine Tabelle mit Spalten für verschiedene Datentypen (z. B. string, long, DateTime etc) OR nur eine Tabelle mit einem String für den Wert, auf den Sie die Werte serialisieren und deserialisieren müssen? Ich denke, der erste wäre einfacher, und wenn es nicht viele Einstellungen gibt, ist der Aufwand nicht viel? 

Q3 - Können Anwendungseinstellungen dafür verwendet werden? Wenn ja, gibt es spezielle Aufgaben, um hier die Persistenz zu ermöglichen? Was würde in diesem Fall auch mit dem "Standardwert" im Anwendungseinstellungsdesigner passieren? Würde die Standardeinstellung Einstellungen überschreiben, die zwischen der Ausführung der Anwendung gespeichert wurden? (oder müssten Sie NICHT den Standardwert verwenden)

61
Greg

Sie können Application Settings verwenden, um die Datenbank zu verwenden. Dies ist jedoch nicht die beste Option, wenn Sie die Zeit für das Lesen und Schreiben der Einstellungen in Anspruch nehmen (insbesondere, wenn Sie Web-Services verwenden).

Hier sind einige Links, die erläutern, wie dies erreicht und in WPF verwendet werden kann.

Benutzereinstellungen in WPF

Schneller WPF-Tipp: Wie binden Sie WPF-Anwendungsressourcen und -einstellungen?

Ein konfigurierbares Fenster für WPF

61
akjoshi

Sie können Ihre Einstellungsinformationen als Strings von XML im Settings.Default speichern. Erstellen Sie einige Klassen, um Ihre Konfigurationsdaten zu speichern, und stellen Sie sicher, dass sie [Serializable] sind. Anschließend können Sie mit den folgenden Helfern Instanzen dieser Objekte - oder List<T> (oder Arrays T[] usw.) - zu String serialisieren. Speichern Sie jede dieser verschiedenen Zeichenfolgen in ihrem eigenen Settings.Default-Slot in der Settings Ihrer WPF-Anwendung.

Um die Objekte beim nächsten Start der App wiederherzustellen, lesen Sie die Settings-Zeichenfolge und Deserialize auf den erwarteten Typ T (der diesmal explizit als Typargument in Deserialize<T> angegeben werden muss).

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);
}
11
Glenn Slayden

Ich gehe auch lieber mit der Serialisierung zur Datei. XML-Dateien erfüllen meistens alle Anforderungen. Sie können das ApplicationSettings-Build verwenden, aber diese haben einige Einschränkungen und ein definiertes, aber für mich sehr merkwürdiges Verhalten, wo sie gespeichert wurden. Ich habe sie viel benutzt und sie arbeiten. Wenn Sie jedoch die vollständige Kontrolle darüber haben möchten, wie und wo sie gespeichert werden, verwende ich einen anderen Ansatz.

  1. Machen Sie irgendwo eine Klasse mit all Ihren Einstellungen. Ich habe es MySettings genannt.
  2. Implementieren Sie Save and Read für Persistenz
  3. Verwenden Sie sie in Ihrem Anwendungscode

Vorteile:

  • Sehr einfacher Ansatz. 
  • Eine Klasse für Einstellungen. Belastung. Sparen.
  • Alle Ihre Einstellungen sind typsicher.
  • Sie können die Logik für Ihre Anforderungen vereinfachen oder erweitern (Versionierung, viele Profile pro Benutzer usw.).
  • Es funktioniert auf jeden Fall sehr gut (Datenbank, WinForms, WPF, Service, etc ...)
  • Sie können festlegen, wo die XML-Dateien gespeichert werden sollen. 
  • Sie können sie finden und entweder per Code oder manuell bearbeiten 
  • Es funktioniert für jede Bereitstellungsmethode, die ich mir vorstellen kann.

Nachteile: - Sie müssen darüber nachdenken, wo Ihre Einstellungsdateien gespeichert werden sollen. (Sie können jedoch nur 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. Sie können Standardwerte laden oder mit den Benutzereinstellungen überschreiben, indem Sie lediglich prü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 bin damit ziemlich zufrieden.

9
Mat

Der am weitesten verbreitete Ansatz für diese Frage ist: Isolated Storage.

Serialisieren Sie Ihren Steuerungsstatus in XML oder ein anderes Format (besonders einfach, wenn Sie Abhängigkeitseigenschaften mit WPF speichern), und speichern Sie die Datei anschließend im isolierten Speicher des Benutzers.

Wenn Sie die App-Einstellungsroute wählen möchten, habe ich selbst an einer Stelle etwas Ähnliches ausprobiert ... obwohl der folgende Ansatz leicht für die Verwendung von Isolated Storage 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);
        }
6
Jeff

Neben einer Datenbank können Sie folgende Optionen zum Speichern benutzerbezogener Einstellungen haben 

  1. registrierung unter HKEY_CURRENT_USER 

  2. in einer Datei im Ordner AppData

  3. verwenden der Settings-Datei in WPF und durch Festlegen des Bereichs als Benutzer

4
ajay_whiz

Nach meiner Erfahrung ist das Speichern aller Einstellungen in einer Datenbanktabelle die beste Lösung. Sorgen Sie sich nicht einmal 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 Serialisierung/Deserialisierung durchgeführt habe - ein Alptraum. Das Speichern in einer lokalen Datei oder in einer lokalen Registrierung hat ein großes Problem - wenn Sie Ihre App unterstützen müssen und der Computer ausgeschaltet ist - der Benutzer steht nicht davor - Sie können nichts tun geändert und Viola nicht zu vergessen, dass Sie die Einstellungen vergleichen können ....

3
Adam

Normalerweise mache ich dies, indem ich eine benutzerdefinierte Einstellungsklasse [Serializable] definiere und sie einfach auf die Festplatte serialisiere. In Ihrem Fall können Sie es genauso einfach als String-Blob in Ihrer SQLite-Datenbank speichern. 

1
Doobi

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. Falls jemand nach einer VB.net-Lösung sucht, ist hier die Klasse, die ich aufgebaut 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
0
Scott
  1. 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 die Konfiguration einer Person schnell ändern oder einem neuen Teilnehmer eine Standardkonfiguration (oder ein Teammitglied) zuweisen.

  2. Wenn die Einstellungen mit der Veröffentlichung neuer Versionen der Anwendung wahrscheinlich zunehmen, sollten Sie die Daten als Blobs speichern, die dann von der Anwendung deserialisiert werden können. Dies ist besonders nützlich, wenn Sie so etwas wie Prism verwenden, das Module entdeckt, da Sie nicht wissen können, welche Einstellungen ein Modul zurückgibt. Die Blobs könnten mit dem aus Username/Computer zusammengesetzten Schlüssel eingegeben werden. Auf diese Weise können Sie für jede Maschine unterschiedliche Einstellungen vornehmen.

  3. Ich habe die eingebaute Settings-Klasse nicht viel benutzt, daher verzichte ich auf Kommentare. :)

0
Will_Piuvans