Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 按名称删除事件_Vb.net_Events_Handler_Removeall - Fatal编程技术网

Vb.net 按名称删除事件

Vb.net 按名称删除事件,vb.net,events,handler,removeall,Vb.net,Events,Handler,Removeall,我想使用VisualBasic.Net从WinForms控件中删除特定的处理程序 例如: 我有一个Windows.Forms.ToolStripButton,其中注册了一个单击事件以保存数据 现在我需要从按钮中删除此事件,但我无法访问registerd事件方法!!我几乎不知道用的是哪个把手。在我的例子中,“点击” 为了更好地理解:我必须为GridView编写一个扩展。当选择多行时,我必须为所选行集成批量编辑。为此,我需要为savebutton注册一个新的点击事件,并删除旧的点击事件。但我无法访问

我想使用VisualBasic.Net从WinForms控件中删除特定的处理程序

例如:

我有一个Windows.Forms.ToolStripButton,其中注册了一个单击事件以保存数据

现在我需要从按钮中删除此事件,但我无法访问registerd事件方法!!我几乎不知道用的是哪个把手。在我的例子中,“点击”

为了更好地理解:我必须为GridView编写一个扩展。当选择多行时,我必须为所选行集成批量编辑。为此,我需要为savebutton注册一个新的点击事件,并删除旧的点击事件。但我无法访问事件处理程序的地址。我只有注册事件的按钮

这就是我迄今为止所尝试的:

Dim btnSaveEventInfo = btnSave.GetType.GetEvent("Click")
Dim method = Activator.CreateInstance(btnSaveEventInfo.GetType, True)

RemoveHandler btnSave.Click, method
这会引发InvalidCastException

有人知道吗


Gr33tz黑鱼

哇。这是一个比我想象的更难解决的问题。这是可能的,但我要警告你,这真是一团糟。最终,您需要做的是获取事件的
委托
对象。一旦完成,删除事件处理程序就很容易了,因为您可以执行以下操作:

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控件的事件处理程序是以自定义方式实现的(尽管它们彼此一致),因此获取控件事件的委托就更复杂了。有一篇关于这一切的精彩评论。对于我来说,在这里重复所有信息太长了,但我用它来组合一个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

该方法最初是如何注册为事件处理程序的?Methdo的可能副本已注册为处理程序函数:Private Sub btnSave_Click(发送方作为对象,e作为事件参数)处理btnSave。单击SaveChanges()End SubHave您是否尝试将
方法
显式强制转换为
事件处理程序
?显式强制转换会引发与上面所述相同的错误,直到EventHandlerList,当我看到您已经制定了一个post:)+1@MrPaulch干得好!我很高兴知道,我不是唯一一个被卷入这个兔子洞的人。在测试了上述代码之后,它确实从代码中删除了所有的点击处理程序,但只有当处理程序添加了:AddHandler btnSaveClick,clickHandler在我的例子中,处理程序被添加到方法中,控件为WithEvents。为此,将永久添加处理程序,因此上述代码无法工作。另请看:@gangfish-Hmmm。是的,这是一个艰难的过程。我想不出任何方法,即使使用反射,也不能用events引用删除
。在这种情况下,我会更加强烈地强调,需要重新考虑您的设计:(@gangfish,或者,如果您无法更改处理事件的代码,也许您可以想出一些方法将按钮包装到另一个类中,或者使用派生的按钮类,允许您首先停止事件的触发。