【发布时间】:2016-11-18 19:55:52
【问题描述】:
有没有办法找到Windows Forms 控件的所有事件处理程序?专门静态定义的事件处理程序?
【问题讨论】:
标签: .net winforms event-handling dynamic
有没有办法找到Windows Forms 控件的所有事件处理程序?专门静态定义的事件处理程序?
【问题讨论】:
标签: .net winforms event-handling dynamic
Windows 窗体对此有很强的反制措施。大多数控件将事件处理程序引用存储在需要秘密“cookie”的列表中。 cookie 值是动态创建的,您无法预先猜到。反射是一个后门,你要知道cookie变量名。例如,Control.Click 事件的名称为“EventClick”,您可以在 Reference Source 或 Reflector 中看到它。
这完全是不切实际的,如果你觉得你在做一些不明智的事情,那么你就走在了正确的轨道上。您可以在this thread 的回答中找到执行此操作的示例代码。
【讨论】:
Windows 窗体控件使用名为 Events 的 EventHandlerList 属性来保存事件处理程序,以便您可以迭代该集合。要确定哪些订阅的处理程序是静态的,您需要使用reflection。
【讨论】:
此代码将获取控件的事件处理程序
Private Function getEventHandlers(ctrl As Control) As System.ComponentModel.EventHandlerList
Dim value As System.ComponentModel.EventHandlerList = Nothing
Try
Dim propInfo As System.Reflection.PropertyInfo = GetType(Control).GetProperty("Events", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Static)
If propInfo IsNot Nothing Then value = CType(propInfo.GetValue(ctrl), System.ComponentModel.EventHandlerList)
Catch ex As Exception
End Try
Return value
End Function
我在多次添加事件处理程序时遇到了问题,从而导致了多个引发的事件。下面将允许您检查控件是否已经具有指定事件的处理程序。
Private Function hasEventHandler(ctrl As Control, Optional eventName As String = "Click") As Boolean
Dim value As Boolean = False
Try
Dim handlerList As System.ComponentModel.EventHandlerList = getEventHandlers(ctrl)
Dim controlEventInfo As System.Reflection.FieldInfo = GetType(Control).GetField("Event" + eventName, Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static)
If controlEventInfo IsNot Nothing Then
Dim eventKey As Object = controlEventInfo.GetValue(ctrl)
Dim EventHandlerDelegate As [Delegate] = handlerList.Item(eventKey)
If EventHandlerDelegate IsNot Nothing Then value = True
End If
Catch ex As Exception
End Try
Return value
End Function
【讨论】: