ここでは、任意の動的イベントのコレクション内のすべてのコントロールに、指定されたデリゲートをイベント ハンドラーとして追加する巧妙な小さな関数を作成しようとしています。私がやろうとしているのは、これを完全に汎用的な関数として記述して、さまざまなプロジェクトで使用できるようにすることです (おそらく、ある種のツール ライブラリに含めることができます)。
基本的には、コントロールのグループ、イベントを処理するデリゲート、および処理するイベントの種類を指定したいと考えています。私が直面している問題は、実行時にイベントを動的に指定する方法がわからないことです。
これが私の「進行中の作業」サブです:
Private Sub AddHandlerToControls(controlList As ControlCollection, eventToHandle As EventHandler, eventHandlerDelegate As Func(Of Object, EventArgs), Optional filterList As List(Of Type) = {})
For Each controlInList As Control In controlList
If controlInList.HasChildren Then
AddHandlerToControls(controlInList.Controls, controlInList.MouseEnter, eventHandlerDelegate, filterList)
End If
If filterList.Count > 0 Then
If filterList.Contains(controlInList.GetType) = False Then
Continue For
End If
End If
AddHandler controlInList.MouseEnter, eventHandlerDelegate
Next
End Sub
理想的には、特に使用するのではなく、ステートメントeventToHandle
の最後にあるパラメーターを使用したいと思います。このような:AddHandler
controlInList.MouseEnter
AddHandler eventToHandle, eventHandlerDelegate
そうすれば、この関数を form.load メソッドで動的に呼び出すことができ、以前に子コントロールに対して自分自身を再帰的に呼び出すサブで行った方法と同じように呼び出すことができます。どういうわけか、「このコントロールのリストでは、このデリゲートを 'MouseEnter' イベント ハンドラーとして使用したい」と言います。そのようです:
AddHandlerToControls(Me.Controls, control.MouseEnter, MouseEnterHandlerDelegate, new List(Of Type) {TextBox, ComboBox})
これはただの希望的観測かもしれません。このレベルの「汎用性」ではこれはまったく不可能だと思い始めていますが、少なくとも質問する必要があると考えた十分に興味深い問題です。
ソリューションの編集:
Reflection を使用するという Jon Skeet の提案は、最終的にはうまくいきました。最終的な関数は次のとおりです。
Private Shared Sub AddHandlerToControls(controlList As Control.ControlCollection, eventToHandle As String, eventHandlerDelegate As MethodInfo, Optional filterList As List(Of Type) = Nothing)
For Each controlInList As Control In controlList
If controlInList.HasChildren Then
AddHandlerToControls(controlInList.Controls, eventToHandle, eventHandlerDelegate, filterList)
End If
If Not filterList Is Nothing Then
If filterList.Contains(controlInList.GetType) = False Then
Continue For
End If
End If
Dim dynamicEventInfo As EventInfo = controlInList.GetType.GetEvent(eventToHandle)
Dim handlerType As Type = dynamicEventInfo.EventHandlerType
Dim eventDelegate As [Delegate] = [Delegate].CreateDelegate(handlerType, eventHandlerDelegate)
dynamicEventInfo.AddEventHandler(controlInList, eventDelegate)
Next
End Sub
そして、私がそれをどのように呼び出し、デリゲートが使用したか:
AddHandlerToControls(Controls, "MouseClick", GetType(MainFrm).GetMethod("MouseClickEventDelegate"), New List(Of Type) From {GetType(TextBox), GetType(ComboBox)})
Shared Sub MouseClickEventDelegate(sender As Object, eventArgs As EventArgs)
sender.SelectAll()
End Sub
これにより、約 20 行のコードで、フォーム上のすべてのテキスト ボックスとコンボ ボックス (かなりの数があります) を設定して、クリックしたときにすべてのテキストを選択することができました。最良の部分は、将来追加する場合、このハンドラーを追加するために戻ることを心配する必要がないことです。実行時に処理されます。それは最もクリーンな解決策ではないかもしれませんが、私にとってはかなりうまくいきました。