諸元
イベントを持つクラスを作成した場合
Formなどでそのイベントを捉えるときは、メンバ宣言するときにWithEventsをつけておけば
コーディングが楽です。
ただしこのとき、Formが閉じられてDisposeされても、イベントハンドラは残っているようで
イベントが発行されたときに拾ってしまいます。
ハンドラをしっかり消すためにはDisposeイベントでメンバの参照をnothingすればOK。
ソース
Raiseが呼び出されたらイベント起こすだけの実験的クラス
Public Class Class1
Public Event TestEvent(sender As Object, e As EventArgs)
Public Sub Raise()
RaiseEvent TestEvent(Me, New EventArgs)
End Sub
End Class
実験クラスのインスタンスをメンバに持ち、
Form2を開いたり実験クラスのRaiseを実行したりする役割
Public Class Form1
Private cl As New Class1
Private WithEvents f As Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
f = New Form2(cl)
f.Show()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
cl.Raise()
End Sub
Private Sub f_Disposed(sender As Object, e As EventArgs) Handles f.Disposed
f = Nothing
End Sub
End Class
実験クラスのイベントを拾ったときにメッセージを出す
Public Class Form2
Private WithEvents cl As Class1
Public Sub New(cl As Class1)
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
Me.cl = cl
End Sub
Private Sub cl_TestEvent(sender As Object, e As EventArgs) Handles cl.TestEvent
MessageBox.Show("!")
End Sub
Private Sub Form2_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Me.cl = Nothing
End Sub
End Class
実行と確認
Form1は最初から実験クラスのインスタンスを持っています。
Button2を押すとインスタンスにイベントを起こさせますが、最初は何も変化しません。
Button1を押すとForm2にインスタンスを渡した上で開きます。
Form2は渡されたインスタンスの発行するイベントを拾ってメッセージボックスを出すので、
Form2を開いてからForm1のButton2を押すと確かに出ます。
Form2を閉じてからButton2を押してもメッセージボックスは出ません。
これはForm2がDisposeしたときにインスタンスへの参照を消しているからであって、放置していれば
Form2がGCによって開放されるまではイベントは拾い続けるでしょう。
( インスタンスがForm2から参照され続けているからForm2は開放されない? ちょっとわかりません)