VB.NET添加任何带委托的EventHandler类型

时间:2018-07-19 00:48:28

标签: vb.net events reflection delegates eventhandler

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

我想做的基本上是创建一个方法,该方法将使用Reflection.EventInfoReflection.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。因此,为了测试,我尝试了下面的代码,它DID起作用了:

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相同类型的委托,那么我可以使它工作。是否可以动态设置变量的类型?如果没有,是否有另一种方法可以将任何控件的事件动态绑定到方法上?

1 个答案:

答案 0 :(得分:0)

我发现了一篇很有帮助的文章(如下)。我要做的是创建一个单独的函数,该函数可以将委托转换为正确的委托类型并将其返回。

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

可以找到帮助的文章: Casting Delegates