none
Applikations-Einstellungen speichern RRS feed

  • Frage

  • Hallo zusammen

    Ich habe eine Klasse entwickelt, um die Position eines Forms zu speichern und zu laden. Da diese Klasse für mehrere Forms ist, habe ich eine Collection erstellt, die als Elemente die die Position etc. enthält:

    Friend Class clsForm
     Private mintWindowState As FormWindowState = FormWindowState.Normal
     Private mobjLocation As Point = New Point(0, 0)
     Private mobjSize As Size = New Size(800, 600)
    
     Public Sub New()
    
     End Sub
    
     Public Sub New(ByVal Location As Point, ByVal Size As Size, ByVal WindowState As FormWindowState)
      mobjLocation = Location
      mobjSize = Size
      mintWindowState = WindowState
     End Sub
    
     Protected Overrides Sub Finalize()
      mobjLocation = Nothing
      mobjSize = Nothing
    
      MyBase.Finalize()
     End Sub
    
     Public Property Location() As Point
      Get
       Return mobjLocation
      End Get
      Set(ByVal Value As Point)
       mobjLocation = Value
      End Set
     End Property
    
     Public Property Size() As Size
      Get
       Return mobjSize
      End Get
      Set(ByVal Value As Size)
       mobjSize = Value
      End Set
     End Property
    
     Public Property WindowState() As FormWindowState
      Get
       Return mintWindowState
      End Get
      Set(ByVal Value As FormWindowState)
       mintWindowState = Value
      End Set
     End Property
    End Class
    

    Nun möchte ich die Collection in den Applikationseinstellungen speichern (mobjCol ist die genannte Collection):

       With My.Settings
        .FormPositions = mobjCol
        .Save()
       End With
    
    

    Dies funktioniert, bis die Applikation geschlossen wird. Danach ist die Setting FormPositions (vom Typ Collection) wieder leer.

    Was mach ich da falsch?

     

    Danke für eure Antwort

    PS: Das speichern eines String-Wertes funktioniert.

    Dienstag, 28. September 2010 15:39

Antworten

  • Hallo,

     Private Sub Close(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
     Try
     mobjCol.Remove(sender.Name)
     Catch
     End Try
    
     Try
     mobjCol.Add(New clsForm(sender.Location, sender.Size, sender.WindowState), sender.Name)
    
     With My.Settings
     .FormPositions = mobjCol
     .Save()
     End With
    
     Catch ex As Exception
     RaiseEvent Close_Error(ex.Message)
     End Try
     End Sub
    End Class
     
    Die Setting FormPositions ist vom Typ Microsoft.VisualBasic.Collection und als Benutzer (Bereich) deklariert.

    das funktioniert so nicht. Eine Collection kann nicht über den SettingsManager serialisiert werden. Zum einen weil die Inhalte untypisiert sind, zum anderen versteht es der SettingsManager nicht eine Key => Value Collection zu serialisieren. Ein typisiertes Dictionary(Of String, clsForm) würde also ebenso wenig funktionieren.

    Ein alternativer Ansatz wäre eine eigene Auflistungsklasse, die von List(Of T) erbt. Diese erleichtert das Handling in Verbindung mit dem Settings Designer, zudem ermöglicht sie die Implementierung spezieller Methoden, um eine Key => Value Zuordnung zu simulieren. Die Klassen FormSettings + FormSetting:

    Public Class FormSetting
     Private m_Name As String
     Private m_WindowState As FormWindowState = FormWindowState.Normal
     Private m_Location As Point = New Point(0, 0)
     Private m_Size As Size = New Size(800, 600)
    
     Public Sub New()
    
     End Sub
    
     Public Sub New(ByVal name As String, _
       ByVal location As Point, _
       ByVal size As Size, _
       ByVal windowState As FormWindowState)
    	 Me.Name = name
    	 Me.Location = location
    	 Me.Size = size
    	 Me.WindowState = windowState
     End Sub
    
     Public Property Name() As String
    	 Get
    		Return m_Name
    	 End Get
    	 Set(ByVal value As String)
    		m_Name = value
    	 End Set
     End Property
    
     Public Property Location() As Point
    	 Get
    		Return m_Location
    	 End Get
    	 Set(ByVal value As Point)
    		m_Location = Value
    	 End Set
     End Property
    
     Public Property Size() As Size
    	 Get
    		Return m_Size
    	 End Get
    	 Set(ByVal value As Size)
    		m_Size = Value
    	 End Set
     End Property
    
     Public Property WindowState() As FormWindowState
    	 Get
    		Return m_WindowState
    	 End Get
    	 Set(ByVal value As FormWindowState)
    		m_WindowState = value
    	 End Set
     End Property
    End Class
    
    Public Class FormSettings
     Inherits List(Of FormSetting)
    
     Public Overloads Function Contains(ByVal name As String) As Boolean
    	Return Me.Exists(Function(t) (t.Name = name))
     End Function
    
     Public Overloads ReadOnly Property Item(ByVal name As String) As FormSetting
    	 Get
    	 Return Me.Find(Function(t) t.Name = name)
    	 End Get
     End Property
    End Class
    

    Um diese Einstellungen in My.Settings bekannt zu machen, ist ein manueller Eingriff in die Settings Deklaration notwending.

    1. Dazu musst Du Dir im Projektmappenexplorer zunächst alle Dateien anzeigen lassen
    2. Öffnest den Zweig "My Project" und
    3. Klickst dort die Datei "Settings.settings" mit der rechten Maustaste an
    4. Wählst den Menüpunkt "Öffnen mit"
    5. Im nachfolgenden Dialog wählst Du "XML Editor" aus
    6. In der geöffneten Datei suchst Du Deinen Eintrag, der die Einstellungen bisher als Collection speichern sollte
    7. Änderst bei diesem Eintrag den Wert im Type Attribut in "Namespace.FormSettings"
      Namespace ersetzt Du hier natürlich durch den passenden Namespace Bezeichner Deines Projekts.
    8. Änderungen speichern und Projekt neu erstellen lassen.

    Anwendung im Formular:

    Public Class Form1
    
     Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    	 If My.Settings.Forms Is Nothing Then
    		My.Settings.Forms = New FormSettings
    	 End If
     End Sub
    
     Private Sub Button1_Click(ByVal sender As System.Object, _
                  ByVal e As System.EventArgs) Handles Button1.Click
    
    	 If My.Settings.Forms.Contains("Foo") Then
    	  Debug.Print("Using existing setting")
    	  My.Settings.Forms.Item("Foo").WindowState = FormWindowState.Maximized
    
    	 Else
    	  Debug.Print("Creating new setting")
    	  My.Settings.Forms.Add(New FormSetting("Foo", _
    			     New Point(10, 10), _
    			     New Size(700, 400), _
    			     FormWindowState.Normal))
    	 End If
    
        My.Settings.Save()
     End Sub
    End Class

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert eipalittau Mittwoch, 29. September 2010 08:32
    Mittwoch, 29. September 2010 05:21
  • Hallo,

    Kleiner Wehrmutstropfen: Wie kann ich die Klasse clsForm verstecken. (Da nun von clsForm geerbt wird, kann sie nicht mehr Friend sein)

    die beiden Klassen FormSettings + FormSetting müssen öffentlich sichtbar sein, sonst funktioniert das Serialisieren nicht. Du kannst höchstens dafür sorgen, dass die beiden Klassen nicht im Objektbrowser bzw. im Codeeditor angezeigt werden, dazu wendest Du das Attribut EditorBrowsable auf die beiden Klassen an:

    <System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> _
    Class FormSettings
    

    Allerdings wirkt das für das gesamte Projekt und kann beim Entwickeln eher hinderlich sein.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert eipalittau Mittwoch, 29. September 2010 19:43
    Mittwoch, 29. September 2010 11:54

Alle Antworten

  • Hallo,

    Nun möchte ich die Collection in den Applikationseinstellungen speichern (mobjCol ist die genannte Collection):

      With My.Settings
      .FormPositions = mobjCol
      .Save()
      End With
    
     

    Dies funktioniert, bis die Applikation geschlossen wird. Danach ist die Setting FormPositions (vom Typ Collection) wieder leer.

    Was mach ich da falsch?

    das ist nicht so leicht zu sagen, da Du leider nicht zeigst, von welchem Typ Dein Setting "FormPositions", sowie Deine Variable "mobjCol" sind. Einen Typ "Collection" gibt es bei der Auswahl der Settings nicht. Oder wie hast Du die Einstellung "FormPositions" erstellt?


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    Dienstag, 28. September 2010 15:56
  • Hallo,

    ich habe Dein doppeltes Posting im allgemeinen Visual Basic Forum gelöscht. Es ist ausreichend, wenn Du Deine Anfrage in einem Forum stellst. Sonst kann es vorkommen, dass zur Lösung des Problems andere Teilnehmer die Information nicht mitbekommen, die im jeweils anderen Thread gegeben wurden. Wenn Du meinst, dass Dein Beitrag bessser im allgemeinen Visual Basic Forum untergebracht wäre, gib mir bitte Bescheid, dann verschiebe ich diesen Thread entsprechend.

    Danke für Dein Verständnis!


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    Dienstag, 28. September 2010 16:16
  • Hier mal der komplette Code:

    Public Class Formular
     Public Event Open_Error(ByVal Message As String)
     Public Event Close_Error(ByVal Message As String)
    
     Private mobjCol As Collection = Nothing
     Private mobjItem As clsForm = Nothing
    
     Public Sub New(ByRef Target As Form)
      mobjCol = My.Settings.FormPositions
      If mobjCol Is Nothing Then mobjCol = New Collection
    
      Try
       mobjItem = mobjCol.Item(Target.Name)
      Catch
       mobjItem = New clsForm()
      End Try
    
      AddHandler Target.Load, AddressOf Open
      AddHandler Target.FormClosing, AddressOf Close
     End Sub
    
     Protected Overrides Sub Finalize()
      mobjCol.Clear()
      mobjCol = Nothing
      mobjItem = Nothing
    
      MyBase.Finalize()
     End Sub
    
     Private Sub Open(ByVal sender As System.Object, ByVal e As System.EventArgs)
      sender.Location = mobjItem.Location
      sender.Size = mobjItem.Size
      sender.WindowState = mobjItem.WindowState
     End Sub
    
     Private Sub Close(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
      Try
       mobjCol.Remove(sender.Name)
      Catch
      End Try
    
      Try
       mobjCol.Add(New clsForm(sender.Location, sender.Size, sender.WindowState), sender.Name)
    
       With My.Settings
        .FormPositions = mobjCol
        .Save()
       End With
    
      Catch ex As Exception
       RaiseEvent Close_Error(ex.Message)
      End Try
     End Sub
    End Class
    
    Die Setting FormPositions ist vom Typ Microsoft.VisualBasic.Collection und als Benutzer (Bereich) deklariert.

    Dienstag, 28. September 2010 17:17
  • Hallo,

     Private Sub Close(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
     Try
     mobjCol.Remove(sender.Name)
     Catch
     End Try
    
     Try
     mobjCol.Add(New clsForm(sender.Location, sender.Size, sender.WindowState), sender.Name)
    
     With My.Settings
     .FormPositions = mobjCol
     .Save()
     End With
    
     Catch ex As Exception
     RaiseEvent Close_Error(ex.Message)
     End Try
     End Sub
    End Class
     
    Die Setting FormPositions ist vom Typ Microsoft.VisualBasic.Collection und als Benutzer (Bereich) deklariert.

    das funktioniert so nicht. Eine Collection kann nicht über den SettingsManager serialisiert werden. Zum einen weil die Inhalte untypisiert sind, zum anderen versteht es der SettingsManager nicht eine Key => Value Collection zu serialisieren. Ein typisiertes Dictionary(Of String, clsForm) würde also ebenso wenig funktionieren.

    Ein alternativer Ansatz wäre eine eigene Auflistungsklasse, die von List(Of T) erbt. Diese erleichtert das Handling in Verbindung mit dem Settings Designer, zudem ermöglicht sie die Implementierung spezieller Methoden, um eine Key => Value Zuordnung zu simulieren. Die Klassen FormSettings + FormSetting:

    Public Class FormSetting
     Private m_Name As String
     Private m_WindowState As FormWindowState = FormWindowState.Normal
     Private m_Location As Point = New Point(0, 0)
     Private m_Size As Size = New Size(800, 600)
    
     Public Sub New()
    
     End Sub
    
     Public Sub New(ByVal name As String, _
       ByVal location As Point, _
       ByVal size As Size, _
       ByVal windowState As FormWindowState)
    	 Me.Name = name
    	 Me.Location = location
    	 Me.Size = size
    	 Me.WindowState = windowState
     End Sub
    
     Public Property Name() As String
    	 Get
    		Return m_Name
    	 End Get
    	 Set(ByVal value As String)
    		m_Name = value
    	 End Set
     End Property
    
     Public Property Location() As Point
    	 Get
    		Return m_Location
    	 End Get
    	 Set(ByVal value As Point)
    		m_Location = Value
    	 End Set
     End Property
    
     Public Property Size() As Size
    	 Get
    		Return m_Size
    	 End Get
    	 Set(ByVal value As Size)
    		m_Size = Value
    	 End Set
     End Property
    
     Public Property WindowState() As FormWindowState
    	 Get
    		Return m_WindowState
    	 End Get
    	 Set(ByVal value As FormWindowState)
    		m_WindowState = value
    	 End Set
     End Property
    End Class
    
    Public Class FormSettings
     Inherits List(Of FormSetting)
    
     Public Overloads Function Contains(ByVal name As String) As Boolean
    	Return Me.Exists(Function(t) (t.Name = name))
     End Function
    
     Public Overloads ReadOnly Property Item(ByVal name As String) As FormSetting
    	 Get
    	 Return Me.Find(Function(t) t.Name = name)
    	 End Get
     End Property
    End Class
    

    Um diese Einstellungen in My.Settings bekannt zu machen, ist ein manueller Eingriff in die Settings Deklaration notwending.

    1. Dazu musst Du Dir im Projektmappenexplorer zunächst alle Dateien anzeigen lassen
    2. Öffnest den Zweig "My Project" und
    3. Klickst dort die Datei "Settings.settings" mit der rechten Maustaste an
    4. Wählst den Menüpunkt "Öffnen mit"
    5. Im nachfolgenden Dialog wählst Du "XML Editor" aus
    6. In der geöffneten Datei suchst Du Deinen Eintrag, der die Einstellungen bisher als Collection speichern sollte
    7. Änderst bei diesem Eintrag den Wert im Type Attribut in "Namespace.FormSettings"
      Namespace ersetzt Du hier natürlich durch den passenden Namespace Bezeichner Deines Projekts.
    8. Änderungen speichern und Projekt neu erstellen lassen.

    Anwendung im Formular:

    Public Class Form1
    
     Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    	 If My.Settings.Forms Is Nothing Then
    		My.Settings.Forms = New FormSettings
    	 End If
     End Sub
    
     Private Sub Button1_Click(ByVal sender As System.Object, _
                  ByVal e As System.EventArgs) Handles Button1.Click
    
    	 If My.Settings.Forms.Contains("Foo") Then
    	  Debug.Print("Using existing setting")
    	  My.Settings.Forms.Item("Foo").WindowState = FormWindowState.Maximized
    
    	 Else
    	  Debug.Print("Creating new setting")
    	  My.Settings.Forms.Add(New FormSetting("Foo", _
    			     New Point(10, 10), _
    			     New Size(700, 400), _
    			     FormWindowState.Normal))
    	 End If
    
        My.Settings.Save()
     End Sub
    End Class

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert eipalittau Mittwoch, 29. September 2010 08:32
    Mittwoch, 29. September 2010 05:21
  • Danke Thorsten. Es funktioniert. Schnelle und kompetente Antwort! Ich habe das ganze noch ein bischen umgeschrieben. Es fehlt jedoch noch das Error-Handlung...

    Public Class Formular
     Inherits List(Of clsForm)
    
     Private mobjItem As clsForm = Nothing
    
     Private Sub New()
    
     End Sub
    
     Public Sub New(ByRef Target As Form)
      If My.Settings.FormPositions Is Nothing Then My.Settings.FormPositions = New Formular()
    
      If My.Settings.FormPositions.Contains(Target.Name) Then
       mobjItem = My.Settings.FormPositions.Item(Target.Name)
      Else
       mobjItem = New clsForm()
      End If
    
      AddHandler Target.Load, AddressOf Open
      AddHandler Target.FormClosing, AddressOf Close
     End Sub
    
     Protected Overrides Sub Finalize()
      mobjItem = Nothing
    
      MyBase.Finalize()
     End Sub
    
     Private Overloads Function Contains(ByVal Name As String) As Boolean
      Return Me.Exists(Function(t) (t.Name = Name))
     End Function
    
     Private Overloads ReadOnly Property Item(ByVal name As String) As clsForm
      Get
       Return Me.Find(Function(t) t.Name = name)
      End Get
     End Property
    
     Private Sub Open(ByVal sender As System.Object, ByVal e As System.EventArgs)
      'Prüfen ob Size grösser als Bildschirm und Location in Bildschirm ist.
      sender.Location = mobjItem.Location
      sender.Size = mobjItem.Size
      sender.WindowState = mobjItem.WindowState
     End Sub
    
     Private Sub Close(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
      Dim strName As String = sender.Name
    
      On Error Resume Next
    
      With My.Settings
       If .FormPositions.Contains(strName) Then .FormPositions.Remove(mobjItem)
       .FormPositions.Add(New clsForm(sender.Name, sender.Location, sender.Size, sender.WindowState))
       .Save()
      End With
     End Sub
    End Class
    
    Kleiner Wehrmutstropfen: Wie kann ich die Klasse clsForm verstecken. (Da nun von clsForm geerbt wird, kann sie nicht mehr Friend sein)

    Mittwoch, 29. September 2010 08:38
  • Hallo,

    Kleiner Wehrmutstropfen: Wie kann ich die Klasse clsForm verstecken. (Da nun von clsForm geerbt wird, kann sie nicht mehr Friend sein)

    die beiden Klassen FormSettings + FormSetting müssen öffentlich sichtbar sein, sonst funktioniert das Serialisieren nicht. Du kannst höchstens dafür sorgen, dass die beiden Klassen nicht im Objektbrowser bzw. im Codeeditor angezeigt werden, dazu wendest Du das Attribut EditorBrowsable auf die beiden Klassen an:

    <System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> _
    Class FormSettings
    

    Allerdings wirkt das für das gesamte Projekt und kann beim Entwickeln eher hinderlich sein.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    • Als Antwort markiert eipalittau Mittwoch, 29. September 2010 19:43
    Mittwoch, 29. September 2010 11:54
  • Perfekt! Vielen Dank. genau was ich brauche...
    Mittwoch, 29. September 2010 19:43