[英]AddressOf in Visual Basic .NET
我有通过代码(动态)生成的按钮。 我必须将一个事件(相同)与它们相关联。 我使用AddHandler button.click, AddressOf mysub
。
问题是 mysub 获取一个字符串 ( mysub(string
)),但 AddressOf 不接受例程内的参数。 我怎样才能做到这一点? 也使用 AddressOf 的替代方法。
Public Class Form1
...
Private Sub mysub(ByVal sender As Object, ByVal e As System.EventArgs, ByVal str As String)
...
...
End Sub
...
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
While something
...
Dim btn As New Button
...
AddHandler btn.click, AddressOf mysub 'here the issue
End While
...
End Sub
End Class
听起来你有以下场景
Class MyClass
Public button As Button
Public Sub New()
AddHandler button.Click AddressOf MySub
End Sub
Public Sub MySub(p As String)
End Sub
End Class
如果是这种情况,那么您有几个选择。 最简单的是使用辅助方法。 让它成为事件处理程序,然后调用MySub
函数
Public Sub New()
AddHandler button.Click AddressOf MyHelper
End Sub
Public Sub MyHelper(sender As Object, e As EventArgs)
MySub(TheStringValue)
End Sub
编辑
与 OP 交谈后,问题是将本地从Form1_Load
函数传递到MySub
方法。 如果您使用的是 Visual Studio 2010,最简单的方法是使用Sub
lambda 表达式
Dim theString = ...
AddHandler button.Click (Sub (sender, e) MySub(sender, e))
如果您使用早期版本的 Visual Studio,它会有点困难,因为您需要手动构建一个闭包。
Class Closure
Public TheForm as Form1
Public TheString As String
Public Sub OnClick(sender As Object, e As EventArgs)
TheForm.MySub(sender, e)
End Sub
End Class
...
' In Form1_Load
Dim closure As New Closure
closure.TheForm = Me
closure.TehString = get the string
AddHandler button.Click AddressOfclosure.OnClick
我认为对 AddressOf 真正做了什么和真正是什么存在误解。
AddressOf 只是将 MEMORY ADDRESS 存储到名为 的函数或方法。 阅读有关 .NET Delegates 的内容,您将了解概念,但关键是要了解委托是:.NET 中用于存储方法的 MEMORY ADDRESSES 的类型。 只是。 委托变量是否存储任何方法? 不,不是任何方法,只有签名与委托声明相匹配的方法。
然后你应该了解事件的概念,它非常依赖于委托,因为一个事件需要知道哪个委托将处理它(谁是 eventHandler,哪个是委托)
现在您提到了无法将参数传递给 AddressOf 的问题。 这是你的误会。 您不会向 AddressOf 传递任何参数,因为您直接将内存地址传递给方法或函数,并且该方法或函数将根据其声明已经包含参数。
所以当你发现类似的东西时:
AddHandler button.click, AddressOf mysub
你告诉编译器的是:“我知道被称为 button 的 Button 有能力在点击它时触发事件。所以我想用 mysub 方法处理(委托发生的动作)这个点击事件,无论它在哪里活在记忆里……”
mysub 是单击按钮时将执行的方法。
您想知道要传递什么参数或如何传递参数。 您不传递任何参数,因为按钮单击事件将传递这些参数。 您可以只处理 mysub 方法从按钮接收的参数。
你怎么知道 mysub 应该从按钮接收哪些参数? 因为它们必须是在 Delegate 定义中定义的那些。 请记住,我们说过委托变量不会将内存地址存储到任何方法,而只会存储到签名与附加到按钮事件click的委托的定义相匹配的方法中
所以转到Button事件的定义,你会发现它使用的是委托类型。 查看该委托的签名,您将确切知道该委托存储的方法具有哪些类型的参数。
然而,好的做法是将事件附加到其签名(它可以存储的方法的签名)包含 2 个参数的委托:
第一个参数是发送者,即生成事件的对象。 所以它是一个
sender as Object
第二个参数是一个用更多信息包装任何其他参数的对象,该对象必须是一个 EventArgs(或继承它)
e as EventArgs
作为一个具体的答案。 如果您想要另一种方法来传递将处理按钮单击事件的方法的内存地址,只需不要传递任何内存地址并具有如下函数的内容:
AddHandler button.click, Sub (ByVal sender As Object, ByVal e As System.EventArgs, ByVal str As String)
'do something here
End Sub
所以在这种情况下,你会对编译器说:“当名为 button 的 Button 生成一个点击事件时,我希望你执行这个匿名(它没有名字)方法。据我所知,按钮的点击事件传递 2 个参数,请将第一个参数放在我的 sender 变量中,将第二个参数放在我的 EventArgs 变量中”
AddHandler
运算符不调用处理程序,因此在该命令期间尝试将变量传递给它是没有意义的。 AddHandler
只是告诉框架每当引发事件mysub
需要mysub
方法。
更新您应该查看Button.CommandArgument属性。 这将允许您为可在事件处理程序中访问的按钮分配任意值。 由于该属性属于按钮,因此只有当您要传递的值不会为每个按钮更改时,这才会有所帮助。 换句话说,如果每次按下button1
,您都想传入foo
,这将起作用。 否则,它不会有帮助。
在 Form.Load 中:
btn.CommandArgument = "foo";
在您的处理程序中:
Button btn = (Button)sender;
Console.Write(btn.CommandArgument); //foo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.