我正在尝试在这里编写一个聪明的小函数,该函数将指定的委托作为事件处理程序添加到任何动态事件的集合中的所有控件中。 我正在尝试做的是将其编写为一个完全通用的函数,以便我可以在各种不同的项目中使用它(也许将其包含在某种工具库中(。
基本上,我想指定一组控件、处理事件的委托以及要处理的事件类型。 我遇到的问题是我无法弄清楚如何在运行时动态指定事件。
这是我的"正在进行的工作"子:
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
理想情况下,我想在 AddHandler
语句的末尾使用 eventToHandle
参数,而不是专门使用 controlInList.MouseEnter
. 喜欢这个:
AddHandler eventToHandle, eventHandlerDelegate
这样我就可以在 form.load 方法中动态调用此函数,并像我之前在 sub 中所做的那样调用它,它为子控件递归调用自身。 以某种方式说"对于此控件列表,我想将此委托用作'MouseEnter'事件处理程序"。 这样:
AddHandlerToControls(Me.Controls, control.MouseEnter, MouseEnterHandlerDelegate, new List(Of Type) {TextBox, ComboBox})
这可能只是一厢情愿的想法,我开始认为这在这种"通用性"水平上不太可能,但这是一个足够有趣的问题,我认为我至少应该问一下。
编辑解决方案:
Jon Skeet关于使用Reflection的建议最终对我有用。 这是最后一个函数:
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 行代码。 最好的部分是,如果我将来添加任何处理程序,我不必担心返回添加此处理程序,它会在运行时得到处理。 这可能不是最干净的解决方案,但它最终对我来说效果很好。
两个选项:
-
通过 lambda 表达式指定"订阅委托"。我不想猜测这在 VB 中会是什么样子,但在 C# 中它会是这样的:
(control, handler) => control.MouseEnter += handler;
然后,只需将每个控件传递给委托。
-
将事件名称指定为字符串,并使用反射获取事件并订阅(
Type.GetEvent
然后EventInfo.AddEventHandler
(。