我有通过代码生成的按钮(动态)。我必须将一个事件(相同)与他们联系起来。我使用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
答案 0 :(得分:6)
听起来你有以下情景
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按钮。单击AddressOf closure.OnClick
答案 1 :(得分:0)
AddHandler
运算符不会调用处理程序,因此在该命令期间尝试将变量传递给它是没有意义的。 AddHandler
只是告诉框架,每当引发事件时都需要调用mysub
方法。
<强>更新强>
您应该查看Button.CommandArgument属性。这将允许您为可在事件处理程序中访问的按钮分配任意值。由于该属性属于该按钮,因此只有当您想要传递的值不会因每个按钮而改变时,这才有用。换句话说,如果每按一次button1
,您希望传入foo
,这将有效。否则,它不会有帮助。
在Form.Load中:
btn.CommandArgument = "foo";
在你的经纪人中:
Button btn = (Button)sender;
Console.Write(btn.CommandArgument); //foo
答案 2 :(得分:0)
我认为对于AddressOf真正做到的事实存在误解。
AddressOf只是将MEMORY ADDRESS存储到被调用的函数或方法中。阅读.NET代理,您将获得概念,但关键是要了解委托是: .NET中用于存储方法的MEMORY ADDRESSES的类型。只是。 委托变量是否存储任何方法?不,不是任何方法,只有签名与Delegate声明匹配的方法。
然后你应该学习事件的概念,它非常依赖于Delegates,因为一个事件需要知道代理将处理它(谁是eventHandler,它是一个委托)
现在你提到了无法将参数传递给AddressOf的内容。这是你的误解。您不会将任何参数传递给AddressOf,因为您直接将内存地址传递给方法或函数,并且该方法或函数将根据其声明包含参数。
所以当你找到类似的东西时:
AddHandler button.click, AddressOf mysub
你告诉编译器的是:“我知道Button调用按钮能够在点击它时触发事件。所以我想用mysub方法处理(委托发生的动作)这个click事件它生活在记忆中的任何地方......“
mysub是单击按钮时执行的方法。
您想知道要传递什么参数或如何传递参数。你不传递任何参数,因为它将是传递这些参数的按钮点击事件。您只需处理mysub方法从按钮接收的参数即可。
你怎么知道mysub应该从按钮接收什么参数?因为它们必须是委托定义中定义的那些。请记住,我们说委托变量不会将内存地址存储到任何方法,而只会存储其签名与附加到按钮事件的委托定义相匹配的方法单击
所以转到Button事件的定义,你会发现它正在使用委托类型。查看该委托的签名,您将确切知道该委托存储的方法所具有的参数类型。
然而,好的做法是说应该将事件附加到其签名(它可以存储方法的签名)包含2个参数的代理:
第一个参数是发件人,即生成事件的对象。所以它是
sender as Object
第二个参数是一个包含任何其他参数的对象,包含更多信息,该对象必须是EventArgs(或继承它)
e as EventArgs
作为具体答案。如果你想要一个替代方法来传递一个方法的内存地址来处理你的按钮的click事件,那么就不要传递任何内存地址并拥有一个函数的内容,如:
AddHandler button.click, Sub (ByVal sender As Object, ByVal e As System.EventArgs, ByVal str As String)
'do something here
End Sub
所以在这种情况下你会对编译器说:“当Button命名按钮生成一个click事件时,我希望你执行这个匿名(它没有名字)方法。而且我知道按钮的click事件通过2请将第一个参数放在我的sender变量中,将第二个参数放在我的EventArgs变量“
中