2011-08-18 163 views
1

我有通过代码(动态)生成的按钮。我必须将一个事件(同样)与他们联系起来。我使用AddHandler button.click, AddressOf mysub在Visual Basic .NET中的AddressOf

问题是,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

按钮生成点击,而不是字符串,请仔细考虑一下 –

+0

You didn 't understand ...看到现在我的场景 – Alph

+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 button.Click AddressOf closure.OnClick

+0

+1这是在VB中执行此操作的常用方法... – gbianchi

+0

我添加了我的场景 – Alph

+0

@Alph你想传递给那个函数的字符串是什么? – JaredPar

0

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

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

在Form.Load:

btn.CommandArgument = "foo"; 

在您的处理程序:

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

因此,我正在寻找AddressOf的替代方案。我不擅长VB。 – Alph

+0

替代什么?得到一个没有入口点地址的例程? – Martin

+0

我给了一个替代方案,但可能不是你所希望的。 – Jeff

0

我觉得这是一个什么AddressOf确实,真的是误会。

AddressOf只是将一个MEMORY ADDRESS存储到一个函数或方法中。阅读关于.NET委托,你会得到这个概念,但关键是要了解委托是:在.NET中用于存储方法的MEMORY ADDRESSES的类型。只是。 委托变量是否存储任何方法?不,没有任何方法,只有签名与委托声明相符的方法。

然后你应该了解事件的概念,这是非常重视的代表,只是因为一个事件需要知道什么代表将处理它(谁是事件处理程序,这是一个代表)

现在你提到了一些无法将参数传递给AddressOf的东西。这是你的误解。因为你直接越过存储器地址的方法或功能不传递任何参数AddressOf,并且该方法或函数已经包含的参数按照其声明。

所以,当你发现是这样的:

AddHandler button.click, AddressOf mysub 

你告诉编译器是:“我知道那个叫按钮按钮触发事件的能力上点击它的时候所以我想处理(委托该发生的动作)这个单击事件与方法mysub无论它是生活在记忆..”

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

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

你怎么知道什么参数mysub应该接受来自按钮?因为它们必须是委托定义中定义的那些。请记住,我们说,代理变量不内存地址存储的任何方法,但只有方法的签名附加到按钮事件点击委托的定义

所以还是按钮的定义相匹配事件,你会发现它使用委托类型。查看该委托的签名,您将确切知道该委托存储的方法的参数类型。

然而,良好做法说,事件应该被附加到代表们的签名(该方法的它可以存储签名)包含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 

所以在这如果你会说编译器:“当按钮命名按钮生成一个click事件我要你执行这个匿名的(它没有名字)方法。而且我知道按钮的click事件传递了2个参数,请将第一个参数放在我的sender变量中,第二个参数放在EventArgs变量中“