Einstellungen möglichst einfach und komfortabel speichern

  • WPF

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von thefiloe.

    Einstellungen möglichst einfach und komfortabel speichern

    Hallo VBP-Forum,

    ich habe ein NaviagtionWindow mit mehreren Pages. Eine dieser Pages umfasst die Einstellungen. Sämtliche Einstellungen sind an eine Klasse gebunden.
    Jetzt meine Frage: Wie kann ich möglichst einfach die Werte in dieser Klasse speichern und am Programmstart wieder laden.

    Das Speichern habe ich ja schon hinbekommen mit BinarySerializer oder XmlSerializer, aber beim nächsten Programmstart werden die Einstellungen nicht geladen ?(


    Weiß jemand eine Lösung ??

    Vielen Dank
    Julian
    Wo ist das Problem?
    Genau so wie du sie speicherst musst du sie natürlich auch laden.
    Mach von mir aus im MainViewModel eine Property Settings.
    Und wenn der Getter der Property aufgerufen wird (und der Wert noch null ist sprich das erste mal der Getter aufgerufen wird) einfach über Binary-/Xml-Serializer laden.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Kann das ohne IDE leider nur in C# aber du kannst das sicher auch übersetzen:
    Spoiler anzeigen

    Quellcode

    1. MySettings _settings;public MySettings Settings{ get { return _settings ?? (_settings = LoadSettings()); }}
    2. protected MySettings LoadSettings(){ //hier deserialisieren}


    Was natürlich noch schöner wäre, wenn dies nicht im MainViewModel wäre, sondern in einem extra SettingsViewModel wäre wobei das ganze MySettings-Zeug dann halt die Model Ebene wäre.
    Aber je nach dem ist das auch nen recht akzeptabler Ansatz.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Die Serialisierung:

    VB.NET-Quellcode

    1. Public Class Serialisation
    2. Public Shared Sub Serialisieren(ByVal pfad As String, ByVal Objekt As Object)
    3. Using FS As New FileStream(pfad, FileMode.Create, FileAccess.Write, FileShare.None)
    4. Dim XMLSeri As New XmlSerializer(Objekt.GetType)
    5. XMLSeri.Serialize(FS, Objekt)
    6. End Using
    7. End Sub
    8. Public Shared Sub Serialisieren(ByVal InputStream As Stream, ByVal Objekt As Object)
    9. Dim XMLSeri As New XmlSerializer(Objekt.GetType)
    10. XMLSeri.Serialize(InputStream, Objekt)
    11. End Sub
    12. Public Shared Function DeSerialisieren(Of T)(ByVal pfad As String) As T
    13. Using FS As New FileStream(pfad, FileMode.Open, FileAccess.Read, FileShare.Read)
    14. Dim XMLSeri As New XmlSerializer(GetType(T))
    15. Return DirectCast(XMLSeri.Deserialize(FS), T)
    16. End Using
    17. End Function
    18. Public Shared Function DeSerialisieren(Of T)(ByVal InputStream As Stream) As T
    19. Dim XMLSeri As New XmlSerializer(GetType(T))
    20. Return DirectCast(XMLSeri.Deserialize(InputStream), T)
    21. End Function
    22. End Class



    Testfunktion:

    VB.NET-Quellcode

    1. Module MainProgramm
    2. Sub Main()
    3. Dim Pfad As String = "c:\test.xml"
    4. ' Das Objekt, welches serialisiert werden soll
    5. Dim s As New TestKlasse With {.Name = "Hans", .Alter = 42}
    6. ' Hier wird serialisiert
    7. Serialisation.Serialisieren(Pfad, s)
    8. ' Hier wird ein deserialisiert und das ganze in s2 geschrieben (Das kommt dann in dein Form_Load ereignis)
    9. Dim s2 As TestKlasse = Serialisation.DeSerialisieren(Of TestKlasse)(Pfad)
    10. End Sub
    11. End Module
    12. <Serializable()>
    13. Public Class TestKlasse
    14. Public Property Name As String
    15. Public Property Alter As Integer
    16. End Class



    oder als Extension:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Extension
    2. <System.Runtime.CompilerServices.Extension()>
    3. Public Sub Serialisieren(ByVal Objekt As Object, ByVal pfad As String)
    4. Using FS As New FileStream(pfad, FileMode.Create, FileAccess.Write, FileShare.None)
    5. Dim XMLSeri As New XmlSerializer(Objekt.GetType)
    6. XMLSeri.Serialize(FS, Objekt)
    7. End Using
    8. End Sub
    9. <System.Runtime.CompilerServices.Extension()>
    10. Public Sub Serialisieren(ByVal Objekt As Object, ByVal InputStream As Stream)
    11. Dim XMLSeri As New XmlSerializer(Objekt.GetType)
    12. XMLSeri.Serialize(InputStream, Objekt)
    13. End Sub
    14. <System.Runtime.CompilerServices.Extension()>
    15. Public Sub DeSerialisieren(Of T)(ByRef o As T, ByVal pfad As String)
    16. Using FS As New FileStream(pfad, FileMode.Open, FileAccess.Read, FileShare.Read)
    17. Dim XMLSeri As New XmlSerializer(GetType(T))
    18. o = DirectCast(XMLSeri.Deserialize(FS), T)
    19. End Using
    20. End Sub
    21. <System.Runtime.CompilerServices.Extension()>
    22. Public Sub DeSerialisieren(Of T)(ByRef o As T, ByVal InputStream As Stream)
    23. Dim XMLSeri As New XmlSerializer(GetType(T))
    24. o = DirectCast(XMLSeri.Deserialize(InputStream), T)
    25. End Sub
    26. End Module


    Testaufruf:

    VB.NET-Quellcode

    1. Dim Pfad As String = "c:\test.xml"
    2. Dim s As New TestKlasse With {.Name = "Hans", .Alter = 42}
    3. s.Serialisieren(Pfad)
    4. Dim s2 As New TestKlasse
    5. s2.DeSerialisieren(Pfad)
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „BiedermannS“ ()

    My.Settings wäre noch eine Option. AFAIK lässt sich die Klasse auch an das UI binden. Allerdings implementierte diese Klasse nicht INotifyPropertyChanged, was dazu führt, dass du dann vom CodeBehind aus nichts ändern dürftest.

    Zum Laden der Settings:
    Es gibt doch Application-Events. Vielleicht kannst du das Deserialisieren der Settings-File in einen Loaded-Eventhandler packen.
    Von meinem iPhone gesendet
    Die ganzen Loaded Dinge sind immer etwas kritisch. Das Problem ist einfach, dass wenn du größere Applikationen hast, solltest du nur dann laden wenn es gebraucht wird. Dabei bieten sich eben Properties perfekt an wie mein Beispiel oben zeigt. Hatten nämlich mal ne recht große XBAPP Applikation (also auch WPF) und dort wurden Daten aus Datenbanken geladen, aufbereitet usw,... Irgendwann war es dann jedoch soweit, dass das Laden soo lange dauerte, dass es nicht mehr akzeptabel war. Also haben wir das eben über die Methode gelöst wie ich das oben habe und das mit so ca. allem wo irgendwie auf performance gehen könnte. Das Ergebnis war exakt das was wir haben wollten. Die Applikation lief sehr flüssig schnell und auch die RAM auslastung war deutlich niedriger. Somit kann ich nur sagen, ich würde das nie im ctor oder im loaded laden, denn gerade bei guis merkt man, dass es performance frisst und je nach dem was du machst länger dauert. Hier wird das natürlich eher weniger ins Gewicht fallen aber trotzdem kostet es auch nicht viel Mühe sich an sowas zu gewöhnen.

    Ach ja nochwas. Es ist mir schon öfters aufgefallen, dass hier alle einem Irrtum aufsitzen:
    Wenn man den XmlSerializer verwendet muss die Klassen KEIN Serializable-Attribut besitzen. Natürlich darf diese das haben ABER es muss nicht. Beim BinaryS. muss es dort sein und bei den anderen weiß ich es nicht weil ich diese nie verwendet habe.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    @BiedermannS: Danke für den Tipp :)
    @nikeee13: My.Settings habe ich aufgrund der schlechten Kritik noch nie genutzt.

    @thefiloe: Den C#-Code zu übersetzen ist mir irgendwie nicht gelungen. Aber was ich dem Code entnehmen kann: Du hast eine Klasse mit einer Property und einer Protected Sub drin, oder?
    Deine Variante gefällt mir aufgrund der passablen Erklärung auch gut :thumbup: :thumbup:
    Wenn du mir sie noch ein bisschen mehr erklärst, oder einen entsprechenden Hilfelink gibst, wäre ich dir dankbar :rolleyes:
    Es ist recht simpel. Im Getter der Property wird überprüft ob der Wert null (oder eben Nothing) ist. Wenn ja wird einfach dann eine neue Instanz des Typs angelegt (bei einer Struktur geht das natürlich nicht, da dies nicht null/Nothing sein kann).

    So nen Übersetzer hat das so übersetzt:

    VB.NET-Quellcode

    1. Dim _settings As MySettings Public ReadOnly Property Settings As MySettings Get If _settings = Nothing Then LoadSettings() Return _settings End Get End Property Protected Function LoadSettings() As MySettings End Function


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Danke für die Übersetzung.
    Mir stellt sich nur noch eine Frage. Wie kann ich jetzt Werte speichern und laden ?
    MySettings ist eine Klasse, welche theoretisch auch irgendwie anders lauten kann, oder ?
    Demnach bräuchte ich nur die öffentlichen Properties der Klasse hinzufügen.

    Vielen Dank
    Julian