首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AddressOf在Visual .NET中的应用

AddressOf在Visual .NET中的应用
EN

Stack Overflow用户
提问于 2011-08-18 18:23:12
回答 3查看 15.9K关注 0票数 1

我有通过代码(动态)生成的按钮。我必须把(同样的)事件与他们联系起来。我用AddHandler button.click, AddressOf mysub

问题是mysub获得一个字符串(mysub(string),但是AddressOf不接受例程中的参数。我该怎么做?还使用了AddressOf的替代方案。

代码语言:javascript
复制
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
EN

回答 3

Stack Overflow用户

发布于 2011-08-18 18:28:08

听起来你有下面的场景

代码语言:javascript
复制
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函数

代码语言:javascript
复制
  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 2010,最简单的方法是使用Sub lambda表达式

代码语言:javascript
复制
Dim theString = ...
AddHandler button.Click (Sub (sender, e) MySub(sender, e))

如果您使用的是早期版本的Visual,则会更难一些,因为您需要手动构建一个闭包。

代码语言:javascript
复制
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 AddressOf closure.OnClick

票数 6
EN

Stack Overflow用户

发布于 2014-08-12 00:02:30

我认为对于AddressOf到底做了什么和真正做了什么是有误解的。

AddressOf只是将内存地址存储到被调用的函数或方法中。阅读.NET代理,您将得到这个概念,但关键是要理解委托是:在.NET中存储方法的内存地址的类型。就是这样。委托变量是否存储任何方法?不,不是任何方法,只有签名与代表声明相匹配的方法。

然后,您应该了解事件的概念,它非常附属于代表,仅仅因为事件需要知道哪个委托将处理它(谁是eventHandler,它是一个委托)。

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

所以当你发现这样的东西:

代码语言:javascript
复制
AddHandler button.click, AddressOf mysub

您要告诉编译器的是:“我知道按钮被调用的按钮能够在单击按钮时触发事件。因此,我想处理(委托发生的操作)这个单击事件,它在内存中的任何位置都使用mysub方法。”

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

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

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

因此,转到Button事件的定义,您会发现它使用的是委托类型。查看该委托的签名,您将确切地知道该委托存储的方法的参数类型。

但是,良好的实践表明,事件应该附加到代表,其签名(它可以存储的方法签名)包含两个参数:

  • 第一个参数是发送方,即生成事件的对象。所以这是一个 发送方为对象
  • 第二个参数是一个用更多信息包装任何其他参数的对象,该对象必须是EventArgs (或继承它)。 E为EventArgs

作为一个具体的答案。如果您想要另一种方法传递将处理按钮单击事件的方法的内存地址,只需不传递任何内存地址,并且具有如下函数的内容:

代码语言:javascript
复制
AddHandler button.click, Sub (ByVal sender As Object, ByVal e As System.EventArgs, ByVal str As String)
  'do something here
   End Sub

因此,在这种情况下,您会对编译器说:“当按钮命名按钮生成一个单击事件时,我希望您执行这个匿名(它没有名称)方法。

票数 1
EN

Stack Overflow用户

发布于 2011-08-18 18:33:05

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

UPDATE您应该查看Button.CommandArgument属性。这将允许您为您的按钮分配一个可在事件处理程序中访问的任意值。由于该属性属于该按钮,因此只有在要传递的值不更改每个按钮时才会有所帮助。换句话说,如果您每次按button1,您想传递foo,这将有效。否则,就没有用了。

在Form.Load中:

代码语言:javascript
复制
btn.CommandArgument = "foo";

在您的处理程序中:

代码语言:javascript
复制
Button btn = (Button)sender;
Console.Write(btn.CommandArgument); //foo
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7112203

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档