我想使用VisualBasic .Net从WinForms控件中删除特定的处理程序。
例如:
我有一个Windows.Forms.ToolStripButton,注册了Click-Event以保存数据。
现在我需要从Button中删除此事件,但我无法访问已注册的Event-Method !!我知道哪个Handle被使用了。在我的情况下“点击”
为了更好地理解:我必须为GridView编写扩展。当选择多行时,我必须集成所选行的批量编辑。为此,我需要为保存按钮注册一个新的点击事件并删除旧的。但我没有访问事件处理程序的地址。我只有注册事件的按钮
这是我到目前为止所尝试的:
Dim btnSaveEventInfo = btnSave.GetType.GetEvent("Click")
Dim method = Activator.CreateInstance(btnSaveEventInfo.GetType, True)
RemoveHandler btnSave.Click, method
抛出InvalidCastException
有人有任何想法吗?
Gr33tz gangfish
答案 0 :(得分:2)
哇。这比我想象的要难得多。有可能做到这一点,但我会警告你,这真是一团糟。最终,您需要做的是获取事件的Delegate
对象。一旦你有了这个,删除事件处理程序很容易,因为你可以这样做:
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
对象变得容易,但它没有提供获取该事件的委托的简单方法。从技术上讲,肯定没有办法总是获得委托,因为事件会私有地封装他们的委托,并且可以以任何自定义方式实现。但是,由于大多数事件都是在" normal"通过反射可以使私有代理隐藏在对象中。当然,如果微软决定改变正常情况,所有这一切都会破裂。它编制事件的方式,但由于这是你获得的最佳选择,你会被它困住。
为了进一步复杂化,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