Reputation: 1934
Sigh... I have a class that has properties that have events. The event is fired when a property has changed in value. The instance of the class is a backer for the information on a form. I need to save the information that is in the form for later recall.
The idea here is to bind the properties as datasources to the textboxes and datagridview on the form. That is the driver for the event to update the textbox or datagridview when the value of the class changes.
So...when I use the following code to save a file of a static variable (test) it works fine:
Dim test As String = "Hello"
' Persist to file
Dim save As New SaveFileDialog
If save.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim stream As FileStream = File.Create(save.FileName)
Dim formatter As New BinaryFormatter()
formatter.Serialize(stream, test)
stream.Close()
End If
If I try it using the instance of the class that backs the data it is throwing errors because of the class has events:
Dim test As new ClassWithEvents()
' Persist to file
Dim save As New SaveFileDialog
If save.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim stream As FileStream = File.Create(save.FileName)
Dim formatter As New BinaryFormatter()
formatter.Serialize(stream, test)
stream.Close()
End If
The error:
Type 'System.Windows.Forms.Form' in Assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
All I really want to do is keep the values of the controls on a form for later recall.
Any ideas?
Upvotes: 0
Views: 1060
Reputation: 4001
Since you have said that "All I really want to do is keep the values of the controls on a form for later recall", some possible methods would be to:
loop recursively through all the controls (and sub-controls) on the form and store the relevant properties in a serializable data structure.
Bind your controls to an in-memory database, and serialize your data from that.
Upvotes: 0
Reputation: 942020
The likely failure mode here is that your class has an event that was subscribed. And the target of the event handler was a method that's part of a Form class. Yes, that cannot work, the Form class is not serializable. Nor would you want to serialize the event, it is pretty unlikely to deserialize properly.
You suppress serialization of a member of a class by applying the <NonSerialized>
attribute on the member. Unfortunately that's pretty hard to do in VB.NET, it does not work on a member declared with the Event keyword. VB.NET events are rather special. The workaround is to use a Custom Event instead, one that use a private backing field which you can prevent from getting serialized. That looks like this:
<Serializable()> _
Class ClassWithEvents
<NonSerialized()> _
Private Events As New System.ComponentModel.EventHandlerList
Public Custom Event Foo As EventHandler
AddHandler(ByVal value As EventHandler)
Events.AddHandler("foo", value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
Events.RemoveHandler("foo", value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
CType(Events("foo"), EventHandler).Invoke(sender, e)
End RaiseEvent
End Event
'' etc..
End Class
You'll have to do that for every event in the class. You can re-use the Events variable, just change "foo" to "bar". Not a lot of fun of course. Do consider a dedicated class that only has the properties you want to serialize as an alternative.
Upvotes: 1