AddressOf в Visual Basic .NET - PullRequest
       50

AddressOf в Visual Basic .NET

1 голос
/ 18 августа 2011

У меня есть кнопки, сгенерированные с помощью кода (динамически). Я должен связать событие (то же самое) с ними. Я использую 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

Ответы [ 3 ]

6 голосов
/ 18 августа 2011

Похоже, у вас есть следующий сценарий

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

EDIT

После разговора с OP проблема заключается в передаче локального из функции Form1_Load в метод MySub. Если вы используете Visual Studio 2010, самый простой способ сделать это с помощью Sub лямбда-выражения

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.Нажмите AddressOf закрытия. OnClick

0 голосов
/ 12 августа 2014

Я думаю, что существует недопонимание того, что AddressOf действительно делает и чем является на самом деле.

AddressOf просто хранит АДРЕС ПАМЯТИ для вызываемой функции или метода.Прочитайте о делегатах .NET, и вы поймете концепцию, но суть в том, чтобы понять, что делегатом является: тип в .NET для хранения АДРЕСОВ ПАМЯТИ методов.Только то.Хранит ли переменная делегата какой-либо метод?Нет, не какой-либо метод, только методы, подпись которых совпадает с заявлением делегата.

И тогда вы должны узнать о концепции событий, которая очень привязана к делегатам просто потому, что событие должно знать, чтоDelegate будет обрабатывать это (кто является EventHandler, который является делегатом)

Теперь вы упомянули что-то из невозможности передать аргументы в AddressOf.Это твое недоразумение.Вы не передаете никакие аргументы в AddressOf, потому что вы напрямую передаете адрес памяти методу или функции, и этот метод или функция уже будет содержать аргументы в соответствии с его объявлением.

Так что, когда вы найдете что-то вроде:

AddHandler button.click, AddressOf mysub

то, что вы говорите компилятору: «Я знаю, что кнопка, вызываемая кнопкой, имеет возможность инициировать события при нажатии на нее. Поэтому я хочу обработать (делегировать действие, которое происходит) этособытие click с методом mysub, где бы оно ни находилось в памяти .. "

mysub - метод, который будет выполняться при нажатии кнопки.

Вам было интересно, какие аргументы передать иликак передать аргументы.ВЫ не передаете никаких аргументов, потому что это будет событие нажатия кнопки, которое передаст эти аргументы.Вы можете просто обрабатывать параметры, которые метод mysub получает от кнопки.

А как узнать, какие параметры mysub должен получить от кнопки?Потому что они ДОЛЖНЫ быть теми, которые определены в определении делегата.Помните, что мы говорили, что переменные-делегаты не хранят адреса памяти для какого-либо метода, а только для методов, сигнатура которых соответствует определению делегата, присоединенного к событию кнопки 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 генерирует событие click, я хочу, чтобы вы выполнили этот анонимный (без имени) метод. И поскольку я знаю, что событие click кнопки передает 2 аргумента, введитепервый аргумент в моей переменной отправителя и второй аргумент в моей переменной EventArgs "

0 голосов
/ 18 августа 2011

Оператор AddHandler не вызывает обработчик, поэтому нет смысла пытаться передать ему переменную во время этой команды.AddHandler просто сообщает платформе, что метод mysub необходимо вызывать всякий раз, когда происходит событие.

ОБНОВЛЕНИЕ Вы должны взглянуть на свойство Button.CommandArgument .Это позволит вам назначить произвольное значение для вашей кнопки, которое будет доступно в вашем обработчике событий.Поскольку свойство принадлежит кнопке, это поможет, только если значение, которое вы хотите передать, не изменится для каждой кнопки.Другими словами, если каждый раз, когда вы нажимаете button1, вы хотите передать foo, это будет работать.В противном случае это не поможет.

В форме. Загрузка:

btn.CommandArgument = "foo";

В вашем обработчике:

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