Visual Basic .NET 中的 AddressOf

发布于 2024-11-30 10:38:57 字数 703 浏览 0 评论 0原文

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

I have buttons generated through code (dynamically). I have to associate an event (the same) to them. I use AddHandler button.click, AddressOf mysub.

The issue is that mysub gets a string (mysub(string)), but AddressOf doesn't accept a parameter inside the routine. How can I do this? Using also an alternative to 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

廻憶裏菂餘溫 2024-12-07 10:38:57

听起来您有以下情况

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 按钮.Click AddressOf 关闭.OnClick

It sounds like you have the following scenario

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

If that's the case then you have a couple of options. The simplest is to use a helper method. Have it be the event handler and then call the MySub function

  Public Sub New() 
    AddHandler button.Click AddressOf MyHelper
  End Sub

  Public Sub MyHelper(sender As Object, e As EventArgs)
    MySub(TheStringValue)
  End Sub

EDIT

After talking with OP the problem is passing a local from the Form1_Load function into the MySub method. If you're using Visual Studio 2010 the easiest way to do this is with a Sub lambda expression

Dim theString = ...
AddHandler button.Click (Sub (sender, e) MySub(sender, e))

If your using an earlier version of Visual Studio it's a bit harder because you need to manually build up a closure.

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

红焚 2024-12-07 10:38:57

我认为对于 AddressOf 的真正作用和本质存在误解。

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

然后你应该了解事件的概念,它与委托非常相关,只是因为事件需要知道哪个委托将处理它(谁是eventHandler,它是一个委托)

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

因此,当您发现类似的内容时:

AddHandler button.click, AddressOf mysub

您告诉编译器的是:“我知道称为按钮的按钮具有在单击它时触发事件的能力。所以我想处理(委托发生的操作)这个单击事件使用 mysub 方法,无论它位于内存中。”

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

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

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

所以去吧查看Button事件的定义,你会发现它使用的是委托类型。查看该委托的签名,您将确切地知道该委托存储的方法所具有的参数类型。

然而,好的实践表明,事件应该附加到其签名(它可以存储的方法的签名)包含 2 个参数的委托:

  • 第一个参数是发送者,即生成事件的对象。所以这是一个

    发送者作为对象
    
  • 第二个参数是一个用更多信息包装任何其他参数的对象,该对象必须是EventArgs(或继承它)

    e 作为 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 变量中的第二个参数”

I think there is a misunderstanding about what AddressOf really does and really is.

AddressOf is simply storing a MEMORY ADDRESS to a function or method called . Read about .NET Delegates and you will get the concept but the key is to understand that a delegate is:
a type in .NET to store MEMORY ADDRESSES of methods. Just that.
Does a delegate variable store any method? No, not any method, only the methods whose signature matches the declaration of the Delegate.

And then you should learn about the concept of Events, which is very attached to the Delegates simply because an Event needs to know what delegate will handle it (who is the eventHandler, which is a delegate)

Now you mentioned something of being unable to pass arguments to the AddressOf. This is your misunderstanding. You don't pass any arguments to AddressOf because you pass directly a memory address to a method or function, and that method or function will contain already the arguments as per its declaration.

So when you find something like:

AddHandler button.click, AddressOf mysub

what you are telling to the compiler is: "I know that the Button called button has the ability to trigger events when clicked on it. So I want to handle (delegate the action that happens) this click event with the method mysub wherever it is living in memory.."

mysub is the method that it will be executed when the button is clicked.

You were wondering what arguments to pass or how to pass arguments. YOU DON'T pass any arguments because it will be the button click event who will pass these arguments. You can just handle the parameters that the method mysub receives from the button.

And how do you know what parameters mysub should receive from the button? Because they MUST be the ones defined in the Delegate definition. Remember that we said that delegate variables don't store memory addresses to any method but only to methods whose signature matches the definition of the delegate attached to the button event click

So go to the definition of the Button event and you will find that it is using a delegate type. Have a look at the signature of that delegate and you will know exactly what are the type of arguments that the methods this delegate store have.

However the good practices say that the Events should be attached to Delegates whose signature (the method's signature it can store) contains 2 arguments:

  • First argument is the sender, the object that generated the event. So it is a

    sender as Object
    
  • Second argument is an object that wraps any other parameter with more information, the object must be a EventArgs (or inherit it)

    e as EventArgs
    

As a specific answer. If you want an alternative to pass the memory address of a method that will handle the click event of your button, simply don't pass any memory address and have the content of a function like:

AddHandler button.click, Sub (ByVal sender As Object, ByVal e As System.EventArgs, ByVal str As String)
  'do something here
   End Sub

so in this case you would say to the compiler: "when the Button named button generates a click event I want you to execute this anonymous (it has no name) method. And as I know that the button's click event passes 2 arguments, please put the first argument in my sender variable and the second argument in my EventArgs variable"

極樂鬼 2024-12-07 10:38:57

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

更新
您应该查看 Button.CommandArgument< /a> 属性。这将允许您为按钮分配任意值,该值可在事件处理程序中访问。由于该属性属于按钮,因此只有当您要传递的值不会针对每个按钮发生更改时,这才会有帮助。换句话说,如果每次按 button1 时,都想传入 foo,这样就可以了。否则,它不会有任何帮助。

在 Form.Load 中:

btn.CommandArgument = "foo";

在您的处理程序中:

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

The AddHandler operator does not call the handler so it doesn't make sense to try to pass it a variable during that command. AddHandler just tells the framework that the mysub method needs to be called whenever the event is raised.

UPDATE
You should look into the Button.CommandArgument property. This will allow you to assign an arbitrary value to your button that will be accessible in your event handler. Since the property belongs to the button, this will only help if the value you want to pass will not change for each button. In other words, if every time you press button1, you want to pass in foo, this will work. Otherwise, it wont be helpful.

In Form.Load:

btn.CommandArgument = "foo";

In your handler:

Button btn = (Button)sender;
Console.Write(btn.CommandArgument); //foo
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文