繁体   English   中英

Visual Basic .NET 中的 AddressOf

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM