0

ため息...イベントを持つプロパティを持つクラスがあります。このイベントは、プロパティの値が変更されたときに発生します。クラスのインスタンスは、フォーム上の情報のバッカーです。後で思い出せるように、フォーム内の情報を保存する必要があります。

ここでの考え方は、プロパティをデータソースとしてフォームのテキストボックスとデータグリッドビューにバインドすることです。これは、クラスの値が変更されたときにイベントがテキストボックスまたはデータグリッドビューを更新するためのドライバーです。

したがって...次のコードを使用して静的変数(テスト)のファイルを保存すると、正常に動作します:

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

データをバックアップするクラスのインスタンスを使用して試してみると、クラスにイベントがあるため、エラーがスローされます。

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

エラー:

アセンブリ 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' の 'System.Windows.Forms.Form' と入力すると、シリアル化可能としてマークされません。

私が実際にやりたいことは、フォーム上のコントロールの値を保持して、後で思い出せるようにすることだけです。

何か案は?

4

2 に答える 2

1

ここで考えられる失敗モードは、サブスクライブされたイベントがクラスにあることです。イベント ハンドラーのターゲットは、Form クラスの一部であるメソッドでした。はい、それは機能しません。 Form クラスはシリアル化できません。また、イベントをシリアル化する必要もありません。適切に逆シリアル化する可​​能性はほとんどありません。

<NonSerialized>メンバーに属性を適用することにより、クラスのメンバーのシリアル化を抑制します。残念ながら、これを VB.NET で行うのはかなり難しく、Event キーワードで宣言されたメンバーでは機能しません。VB.NET イベントはかなり特殊です。回避策は、シリアル化を防ぐことができるプライベート バッキング フィールドを使用するカスタム イベントを代わりに使用することです。それは次のようになります。

<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

クラスのすべてのイベントでこれを行う必要があります。「foo」を「bar」に変更するだけで、Events 変数を再利用できます。もちろん、あまり楽しいことではありません。代わりに、シリアル化するプロパティのみを持つ専用クラスを検討してください。

于 2013-10-02T22:05:13.980 に答える
0

「私が本当にやりたいことは、フォームにコントロールの値を保持して後で呼び出すことだけです」と述べたので、いくつかの可能な方法は次のとおりです。

  1. フォーム上のすべてのコントロール (およびサブコントロール) を再帰的にループし、関連するプロパティをシリアル化可能なデータ構造に格納します。

  2. コントロールをメモリ内データベースにバインドし、そこからデータをシリアル化します。

于 2013-10-02T23:58:31.227 に答える