哇。这比我预料的要难得多。这是可能的,但我会警告你,这真是一团糟。最终,你需要做的是获得事件的对象。一旦你的,移除事件处理很容易,因为你可以做这样的事情:
Dim d As [Delegate] = ' ... (we'll figure this out later)
For Each handler As [Delegate] In d.GetInvocationList()
RemoveHandler btnSave.Click, DirectCast(handler, EventHandler)
Next
然而,得到了代表的事件是特别困难。反射可以很容易地获得任何所需事件的EventInfo
对象,但它并不提供获取该事件委托的简单方法。从技术上讲,当然,总是无法获得委托,因为事件私自封装了它们的委托,并且可以以任何自定义的方式实现。但是,由于大多数事件都是以“正常”方式实现的,因此可以通过反射来将私人代理隐藏在对象中。当然,如果微软决定改变编写事件的“正常”方式,那么所有这些都会中断,但由于这是您获得的最佳选择,因此您一直坚持使用它。
更复杂的是,对于WinForm的事件处理程序控制被在自定义的方式来实现(尽管所有始终与对方),因此要获得一个控件的事件委托是更加复杂。在this page of Bob Powell's blog上有这方面的优秀报道。这太漫长,我在这里重复所有的信息,但我已经用它放在一起的怎么解决您的具体情况VB.NET例如:
Dim currType As Type = btnSave.GetType()
Dim eventFieldInfo As FieldInfo = Nothing
Do
eventFieldInfo = currType.GetField("EventClick", BindingFlags.Static Or BindingFlags.Instance Or BindingFlags.NonPublic)
If eventFieldInfo Is Nothing Then
currType = currType.BaseType
End If
Loop While eventFieldInfo Is Nothing
Dim ehl As EventHandlerList = DirectCast(btnSave.GetType().GetProperty("Events", BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.FlattenHierarchy).GetValue(btnSave), EventHandlerList)
Dim d As [Delegate] = ehl(eventFieldInfo.GetValue(btnSave))
For Each handler As EventHandler In d.GetInvocationList()
RemoveHandler btnSave.Click, handler
Next
参见上面的链接的原因解释以及如何工作。但是,正如我所说的,这是相当丑陋的,并可能会在未来的.NET版本中打破。因此,如果有任何其他方式可以做到这一点,最好使用这些替代方案。例如,如果您可以控制添加事件处理程序的代码,则可以保留对该代理的单独引用,以便稍后将其删除,例如:
Dim myClickHandler As EventHandler = AddressOf btnSave_Click
AddHandler btnSave.Click, myClickHandler
' ...
RemoveHandler btnSave.Click, myClickHandler
该方法如何被注册为事件处理程序首先? – Crono
可能的重复[是否有可能从一个控件“窃取”事件处理程序并将其提供给另一个?](http://stackoverflow.com/questions/293007/is-it-possible-to-steal-an-事件处理程序从一个控制,并给它它到另一个) –
Methdo注册处理函数:私人小组btnSave_Click(发件人为对象,e作为EventArgs)处理btnSave.Click SaveChanges() End Sub – gangfish