VB.NET 添加任何具有委托的事件处理程序类型
VB.NET Add Any EventHandler Type with Delegate
我找到了一些我认为可以解决我的问题的帖子(不多),但在我所有的阅读中我仍然没有找到解决方案。
我想做的基本上是创建一个方法,使用 Reflection.EventInfo
和 Reflection.MethodInfo
将任何给定控件的事件绑定到任何给定对象的方法。我正在使用 Winforms,我很想只使用 WPF,但不幸的是,这不是一个选项。
我有一个摘要 BoundControl
class,它只是一个用于继承控件的空 canvas。其中 class 是下面的函数:
Public Sub CallMethod(eventName As String, sender As Object, e As EventArgs)
...
End Sub
这就是每当引发给定控件的事件时我想要调用的内容。该方法中的逻辑在数据上下文中调用正确的方法(我已将其设置为模仿 WPF)。这工作正常,我的问题实际上是将上述方法绑定到控件的事件。
我使用下面的方法绑定(与上面的方法相同 class)。请注意,我已经删除了不重要的逻辑,比如我的自定义绑定标签 class 以及与我的问题无关的任何其他内容:
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
类型相同的委托,那么我就可以让它工作。是否可以动态设置变量的类型?如果没有,是否有另一种方法可以将任何控件的事件动态绑定到方法?
我找到了一篇有用的文章(如下)。我必须做的是创建一个单独的函数,该函数将 return 委托转换为正确的委托类型。
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
我找到了一些我认为可以解决我的问题的帖子(不多),但在我所有的阅读中我仍然没有找到解决方案。
我想做的基本上是创建一个方法,使用 Reflection.EventInfo
和 Reflection.MethodInfo
将任何给定控件的事件绑定到任何给定对象的方法。我正在使用 Winforms,我很想只使用 WPF,但不幸的是,这不是一个选项。
我有一个摘要 BoundControl
class,它只是一个用于继承控件的空 canvas。其中 class 是下面的函数:
Public Sub CallMethod(eventName As String, sender As Object, e As EventArgs)
...
End Sub
这就是每当引发给定控件的事件时我想要调用的内容。该方法中的逻辑在数据上下文中调用正确的方法(我已将其设置为模仿 WPF)。这工作正常,我的问题实际上是将上述方法绑定到控件的事件。
我使用下面的方法绑定(与上面的方法相同 class)。请注意,我已经删除了不重要的逻辑,比如我的自定义绑定标签 class 以及与我的问题无关的任何其他内容:
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
类型相同的委托,那么我就可以让它工作。是否可以动态设置变量的类型?如果没有,是否有另一种方法可以将任何控件的事件动态绑定到方法?
我找到了一篇有用的文章(如下)。我必须做的是创建一个单独的函数,该函数将 return 委托转换为正确的委托类型。
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