我正在尝试在这里编写一个聪明的小函数,它将指定的委托作为事件处理程序添加到集合中的所有控件以用于任何动态事件。我想做的是把它写成一个完全通用的函数,这样我就可以在各种不同的项目中使用它(也许包括在某种工具库中)。
基本上我想指定一组控件、处理事件的委托以及要处理的事件类型。我遇到的问题是我无法弄清楚如何在运行时动态指定事件。
这是我的“正在进行的工作”子:
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 方法中动态调用这个函数,并且调用它有点像我之前在 sub 中所做的那样,它递归地为子控件调用自身。不知何故说“对于这个控件列表,我想使用这个委托作为'MouseEnter'事件处理程序”。像这样:
AddHandlerToControls(Me.Controls, control.MouseEnter, MouseEnterHandlerDelegate, new List(Of Type) {TextBox, ComboBox})
这可能只是一厢情愿的想法,我开始认为在这种“通用性”级别上这不太可能,但这是一个足够有趣的问题,我认为我至少应该问一下。
编辑解决方案:
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 行代码。最好的部分是,如果我将来添加任何内容,我不必担心回去添加这个处理程序,它会在运行时得到处理。它可能不是最干净的解决方案,但它最终对我来说效果很好。