【问题标题】:AddressOf in Visual Basic .NETVisual Basic .NET 中的 AddressOf
【发布时间】:2011-10-30 01:04:03
【问题描述】:

我有通过代码(动态)生成的按钮。我必须将一个事件(相同的)与他们联系起来。我用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

【问题讨论】:

  • 按钮产生点击,而不是字符串。想一想。
  • 你不明白......现在看看我的场景。
  • 我需要它!所以,我不能删除它。我也在寻找 AddressOf 的替代品来做我需要的事情。
  • 我很确定按钮单击不能传递字符串。到底是什么字符串?用户点击,你知道是哪个按钮,如果你需要一个字符串,在初始化按钮的时候把它放在按钮TAG中,然后点击就可以使用
  • @Martin:我爱你啊哈哈哈哈:D 简单而完美!我在 Form1_Load 中使用 btn.Tag=string 并在 mysub 中添加了“Dim bttn As Button = DirectCast(sender, Button)”...所以,我可以在需要的地方使用 bttn.Tag :)

标签: .net vb.net addressof


【解决方案1】:

听起来你有以下场景

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

【讨论】:

  • @Alph 你想将什么字符串传递给该函数?
  • 这是一条来自 OleDbDataReader 的记录(字符串),但并不重要。
  • @Alph 重要的是我们知道字符串的来源。 OleDbDataReader 是 Form3_Load 函数的局部变量还是类中的字段?
  • @Alpha 添加了一些希望对您有所帮助的信息
【解决方案2】:

AddHandler 运算符不会调用处理程序,因此在该命令期间尝试将变量传递给它是没有意义的。 AddHandler 只是告诉框架,每当引发事件时都需要调用 mysub 方法。

更新 您应该查看 Button.CommandArgument 属性。这将允许您为您的按钮分配一个任意值,该值可在您的事件处理程序中访问。由于该属性属于按钮,因此仅当您要传递的值不会因每个按钮而改变时,这才会有所帮助。也就是说,如果每次按button1,都想传入foo,这样就行了。否则,它不会有帮助。

在 Form.Load 中:

btn.CommandArgument = "foo";

在您的处理程序中:

Button btn = (Button)sender;
Console.Write(btn.CommandArgument); //foo

【讨论】:

  • 所以,我也在寻找 AddressOf 的替代品。我对VB不是很熟练。
  • 替代什么?在没有入口点地址的情况下调用一个例程?
  • 我提供了另一种选择,但可能不是您所希望的。
【解决方案3】:

我认为对于 AddressOf 的真正作用和实际情况存在误解。

AddressOf 只是将内存地址存储到调用的函数或方法中。阅读 .NET Delegates,您将了解这个概念,但关键是要了解委托是: .NET 中的一种类型,用于存储方法的内存地址。只是。 委托变量是否存储任何方法?不,不是任何方法,只有签名与委托声明匹配的方法。

然后你应该了解Events的概念,它非常依赖于Delegates,仅仅是因为Event需要知道什么delegate会处理它(谁是eventHandler,它是一个delegate)

现在您提到了无法将参数传递给 AddressOf 的问题。这是你的误解。您不向 AddressOf 传递任何参数,因为您直接将内存地址传递给方法或函数,并且该方法或函数将根据其声明已包含参数。

所以当你找到类似的东西时:

AddHandler button.click, AddressOf mysub

您要告诉编译器的是:“我知道被称为按钮的按钮能够在单击它时触发事件。所以我想使用 mysub 方法处理(委托发生的操作)这个单击事件无论它生活在记忆中的什么地方……”

mysub 是单击按钮时将执行的方法。

您想知道要传递哪些参数或如何传递参数。您不要传递任何参数,因为传递这些参数的将是按钮单击事件。您可以只处理 mysub 方法从按钮接收的参数。

你怎么知道 mysub 应该从按钮接收哪些参数?因为它们必须是 Delegate 定义中定义的那些。请记住,我们说过委托变量不会将内存地址存储到任何方法,而只会存储其签名与附加到按钮事件的委托定义匹配的方法单击

所以转到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

所以在这种情况下,您会对编译器说:“当名为按钮的按钮生成单击事件时,我希望您执行此匿名(它没有名称)方法。据我所知,按钮的单击事件传递 2参数,请将第一个参数放在我的 sender 变量中,第二个参数放在我的 EventArgs 变量中”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多