VB.NET使用委托添加任何EventHandler类型

VB.NET使用委托添加任何EventHandler类型,vb.net,events,reflection,delegates,eventhandler,Vb.net,Events,Reflection,Delegates,Eventhandler,我发现了一些我认为可以解决我的问题的帖子(不多),但在我所有的阅读中,我仍然没有一个解决方案 我试图做的基本上是创建一个方法,使用Reflection.EventInfo和Reflection.MethodInfo将任何给定控件的事件绑定到任何给定对象的方法。我使用的是Winforms,我希望只使用WPF,但不幸的是,这不是一个选项 我有一个抽象的BoundControl类,它只是继承控件的一个空画布。该类中的函数如下所示: Public Sub CallMethod(eventName As

我发现了一些我认为可以解决我的问题的帖子(不多),但在我所有的阅读中,我仍然没有一个解决方案

我试图做的基本上是创建一个方法,使用
Reflection.EventInfo
Reflection.MethodInfo
将任何给定控件的事件绑定到任何给定对象的方法。我使用的是Winforms,我希望只使用WPF,但不幸的是,这不是一个选项

我有一个抽象的
BoundControl
类,它只是继承控件的一个空画布。该类中的函数如下所示:

Public Sub CallMethod(eventName As String, sender As Object, e As EventArgs)
...
End Sub
这就是每当引发给定控件的事件时我想要调用的。该方法中的逻辑在数据上下文中调用正确的方法(我将其设置为模仿WPF)。这很好,我的问题实际上是将上述方法绑定到控件的事件

我使用下面的方法绑定(与上面的方法在同一个类中)。请注意,我已经删除了不重要的逻辑,比如我的自定义绑定标记类以及与我的问题无关的任何其他内容:

Public Sub SetEventBind(ByRef ctrl as Control)
    Dim ctrlStr As String = "EventName"
    Dim ctrlEvent as Reflection.EventInfo = ctrl.GetType.GetEvent(ctrlStr)
    Dim eh As EventHandler = (Sub(sender, e) CallMethod(ctrlStr, sender, e))
    ctrlEvent.AddEventHandler(ctrl, eh)
End Sub
我正在尝试在
LinkLabel
上为
LinkClicked
事件运行代码,但我希望这对任何控件的事件都有效。最终发生的情况是,
EventHandler
类型无法转换为
LinkLabelLinkClickedEventHandler
。因此,为了测试,我尝试了下面的代码,它确实起了作用:

Public Sub SetEventBind(ByRef ctrl as Control)
    Dim ctrlStr As String = "EventName"
    Dim ctrlEvent as Reflection.EventInfo = ctrl.GetType.GetEvent(ctrlStr)
    Dim eh As LinkLabelLinkClickedEventHandler = (Sub(sender, e) CallMethod(ctrlStr, sender, e))
    ctrlEvent.AddEventHandler(ctrl, eh)
End Sub
但问题是,
LinkLabelLinkClickedEventHandler
不适用于按钮单击或复选框选中的更改。我还尝试了下面的代码,但没有成功:

Public Sub SetEventBind(ByRef ctrl as Control)
    Dim ctrlStr As String = "EventName"
    Dim ctrlEvent as Reflection.EventInfo = ctrl.GetType.GetEvent(ctrlStr)
    Dim eh As [Delegate] = [Delegate].CreateDelegate(ctrlevent.EventHandlerType, Me, (Sub(sender, e) CallMethod(ctrlStr, sender, e)).Method)
    ctrlEvent.AddEventHandler(ctrl, eh)
End Sub

我想我的问题是多方面的。我想,如果我可以动态创建一个与
ctrlEvent.EventHandlerType
类型相同的委托,那么我就可以让它正常工作。是否可以动态设置变量的类型?如果没有,是否有其他方法可以将任何控件的事件动态绑定到方法?

我发现了一篇有用的文章(见下文)。我要做的是创建一个单独的函数,将委托转换并返回到正确的委托类型

Public Sub SetEventBind(ByRef ctrl As IBoundControl, pBindingTag As BindingTag, pDoAdd As Boolean)
    If pBindingTag.BindingType <> BindType.EventBind Then Exit Sub

    Dim objStr As String = pBindingTag.DataContextBindName
    Dim ctrlStr As String = pBindingTag.ControlBindName

    If Not (String.IsNullOrEmpty(objStr) OrElse String.IsNullOrEmpty(objStr)) Then
        Dim ctrlEvent As Reflection.EventInfo = ctrl.GetType.GetEvent(ctrlStr)

        If Not ctrlEvent Is Nothing Then
            Dim eventDel As [Delegate] = Sub(sender, e)
                                             CallMethod(ctrlStr, sender, e)
                                         End Sub

            Dim convertedDel = CastDelegate(eventDel, ctrlEvent.EventHandlerType)

            ctrlEvent.RemoveEventHandler(ctrl, convertedDel)
            If pDoAdd Then ctrlEvent.AddEventHandler(ctrl, convertedDel)
        End If
    End If
End Sub

Private Function CastDelegate(source As [Delegate], type As Type) As [Delegate]
    Dim delegates As [Delegate]() = source.GetInvocationList()
    Return [Delegate].CreateDelegate(type, delegates(0).Target, delegates(0).Method)
End Function
Public子集合eventbind(ByRef-ctrl作为IBoundControl,pBindingTag作为BindingTag,pDoAdd作为Boolean)
如果pBindingTag.BindingType BindType.EventBind,则退出Sub
Dim objStr As String=pBindingTag.DataContextBindName
Dim ctrlStr As String=pBindingTag.ControlBindName
如果不是(String.IsNullOrEmpty(objStr)或lse String.IsNullOrEmpty(objStr)),则
将ctrlEvent设置为Reflection.EventInfo=ctrl.GetType.GetEvent(ctrlStr)
如果不是,那么ctrlEvent什么都不是
Dim eventDel As[Delegate]=Sub(发送方,e)
调用方法(ctrlStr、发送方、e)
端接头
Dim convertedDel=CastDelegate(eventDel,ctrlEvent.EventHandlerType)
ctrlEvent.RemoveEventHandler(ctrl,convertedDel)
如果为pDoAdd,则为ctrlEvent.AddEventHandler(ctrl,convertedDel)
如果结束
如果结束
端接头
私有函数CastDelegate(源为[Delegate],类型为type)为[Delegate]
Dim委托为[Delegate]()=source.GetInvocationList()
返回[Delegate].CreateDelegate(类型,委托(0).目标,委托(0).方法)
端函数
可在此处找到有帮助的文章: