Как я могу автоматически обрабатывать события формы в другом классе / модуле в VB.NET? - PullRequest
3 голосов
/ 04 мая 2010

Вот мой код:

Public Class Form1

End Class

Public Class Form1Handler
    Inherits Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MsgBox("I")
    End Sub
End Class

Я пытаюсь заставить Form1Handler автоматически обрабатывать события Form1. Как я могу это сделать? Должен ли я использовать модуль вместо? Я делаю это в Visual Basic 2010.

Я не хочу создавать обработчик событий в Form1, а затем передавать его другому классу / модулю. Есть ли какой-нибудь способ автоматически «передать» события из form1 в form1handler?

Ответы [ 4 ]

3 голосов
/ 30 апреля 2012

Я понимаю, что эта тема старая, но я наткнулся на нее в поисках ответа на тот же вопрос. Надеюсь, это может помочь кому-то еще. Ответ xpda был хорош и работает, однако он не работает с кнопками, созданными с помощью дизайнера форм, мое решение работает и является альтернативой методу xpda.

Для этого примера у меня есть Form1 с 2 кнопками (Buttton1 и Button2) и текстовым полем (textbox1). Я также создал модуль (Module1). Я сохранил это простым, и это должно быть легко понять.

Module Module1
Public WithEvents ButtonClick1 As Button = Form1.Button1
Public WithEvents ButtonClick2 As Button = Form1.Button2

Public Sub MyButtons(sender As System.Object, e As System.EventArgs) Handles _
ButtonClick1.Click, 
ButtonClick2.Click

    If sender Is ButtonClick1 Then Form1.TextBox1.Text = "Button1 clicked"
    If sender Is ButtonClick2 Then Form1.TextBox1.Text = "Button2 clicked"
End Sub
End Module

В верхней части модуля вы можете иметь столько событий, сколько вам нужно, по одному на каждый элемент управления. Имейте в виду, что после каждого создаваемого WithEvents (в этом примере) должно следовать событие после предложения Handles в подпункте MyButtons.

Вы должны вызвать подпрограмму во время события загрузки формы, иначе ваша программа не увидит код модуля. Это важно понимать. Если у вас есть более одного сабвуфера, вы должны назвать их всех.

Вызов модуля из формы 1 выглядит следующим образом:

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load

Module1.MyButtons(Nothing,Nothing)

End Sub

Как только это будет сделано, все события нажатия кнопок Button1 и Button2 будут обрабатываться в модуле. Вы можете включить другие события для кнопок в модуль или в форму.

Кстати, я должен также добавить, что вам не нужно создавать одну подпрограмму для обработки всех событий. В этом примере вы могли бы создать 2 подпрограммы, по одной для каждой кнопки. Кроме того, имя сабвуфера никогда не будет называться, поэтому не имеет значения, как вы его называете. События нажатия кнопки будут автоматически обрабатываться модулем, как если бы вы записали его в коде формы.

Еще одна вещь ...

Другим вариантом является создание модуля с подпрограммой, которую вы хотите обработать Button.Click, а затем из меню «Форма» используйте предложение AddHandler.

Module Module1

Public Sub MySub()

Form1.TextBox1.Text = "Button Clicked"

End Sub
End Module

Код формы будет выглядеть следующим образом ...

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load

    AddHandler Button1.Click, AddressOf Module1.MySub

End Sub

Использование этого метода требует отдельного Sub для каждого события button.click, поскольку вы хотите, чтобы каждая кнопка выполняла разные действия.

Ну, это 3 способа сделать одно и то же, каждый со своими сильными и слабыми сторонами.

3 голосов
/ 04 мая 2010

Если вам нужно обработать кнопку или другие события элемента управления вне класса формы, вы можете создать пользовательский элемент управления для наследования элемента управления, а затем обрабатывать события в классе элемента управления пользователя. Например, этот пользовательский элемент управления состоит из внутреннего элемента управления с именем mbutton:

Public Class mb
  Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mButton.Click
  MsgBox("click")
  End Sub
End Class

Вы можете использовать его в основной форме следующим образом:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  b = New mb
  Me.Controls.Add(b)
  b.Name = "testbutton"
  b.Left = 40 : b.Top = 40 : b.Width = 90 : b.Height = 50
End Sub

Событие click обрабатывается внутри класса mb.

2 голосов
/ 22 мая 2013

Я всегда думаю, что хороший ответ - это ответ, который говорит о том, как именно мы можем обрабатывать Form1.Button1.Click (или любой другой) в Form1Handler.

Вы можете сделать свои элементы управления в Form1 как Защищенные , по крайней мере, вместо Личные .

Как?

В Form1.Designer.vb : В конце кода вы должны иметь:

Public Partial Class Form1
    ' ...
    Private Button2 As System.Windows.Forms.Button
    Private Button1 As System.Windows.Forms.Button
End Class

^^ Затем поменяйте частное на защищенное ...

    Protected WithEvents Button2 As System.Windows.Forms.Button
    Protected WithEvents Button1 As System.Windows.Forms.Button

Затем добавьте WithEvents , чтобы убедиться, что ваши кнопки объявлены с событиями.

Или в конструкторе IDE (Visual Studio 2010 или SharpDevelop ) нажмите кнопку и на вкладке свойств установите для ее свойства (списка) Модификаторы значение «Защищено». Это изменит его объявление в Form1.Designer.vb. Я знаю, что не добавит «WithEvents».

Теперь вы можете создать Form1Handler, который наследуется от Form1.

Как добавить обработчик событий в Form1Handler?

Сначала создайте метод, который должен обрабатывать ваше нажатие кнопки, в вашем классе Form1Handler.

Private Sub HandleButtonClick(sender As Object, e As EventArgs)
    ' Instructions for Clicks goes here...
End Sub

Затем создайте метод, который связывает нажатия кнопок с методом выше

Private Sub AddHandlersToButtonClick()
    AddHandler Button1.Click, AddressOf HandleButtonClick
    AddHandler Button2.Click, AddressOf HandleButtonClick
    ' Add as many handlers as you wish, calling as many methods as you wish...
End Sub

Наконец, в вашем классе Form1Handler добавьте вызов к предыдущему методу при загрузке:

Private Sub OnForm1Handler_Load() Handles Me.Load
     AddHandlersToButtonClick()
End Sub

Теперь, когда вы загружаете свой Form1Handler, который наследуется от Form1, HandleButtonClick (..) запускается каждый раз, когда вы нажимаете на Button1 или Button2. Теперь, вы можете захотеть сделать что-то другое, когда вы нажимаете на Button3 и когда ваша мышь входит в Panel1 ... Это то же самое:

    ' Creates as many methods you wish for each of your Form1 Controls,
    ' ensuring those controls are declared as Protected in Form1.
    Private Sub HandleButton1Click(sender As Object, e As EventArgs)
        ' ...
    Private Sub HandleButton2Click(sender As Object, e As EventArgs)
    Private Sub HandleButton3Click(sender As Object, e As EventArgs)
    Private Sub HandlePanel1MouseEnter(sender As Object, e As EventArgs)

    ' Then writes in AddHandlersToButtonClick() the dynamic Events handlers
        AddHandler Button1.Click, AddressOf HandleButton1Click
        AddHandler Button2.Click, AddressOf HandleButton2Click
        AddHandler Button3.Click, AddressOf HandleButton3Click
        AddHandler Panel1.MouseEnter, AddressOf HandlePanel1MouseEnter

Тогда что, если у вас есть 300 кнопок для обработки?

Хорошо! Если, как и я, вы ленивый человек, и вы просто хотите сделать несколько вещей для одних кнопок и вызывать более крупные методы для других, вы можете использовать свойство Tag своей кнопки в IDE:

  • Для Button1 -> Tag = 1
  • Для Button2 -> Tag = 2
  • ...
  • Для Button300 -> Tag = 300

Затем просто используйте метод, представленный выше, и добавьте проверку свойства тега, например:

Private Sub HandleButtonClick(sender As Object, e As EventArgs)
    Dim MyButton As System.Windows.Forms.Button
    Dim MyButtonIndex As Integer

    If TypeOf(MyButton) Is System.Windows.Forms.Button Then ' You should check it's a Button.
        MyButton = CType(sender, System.Windows.Forms.Button) ' Option Strict On - Always !
        If Integer.TryParse(MyButton.Tag.ToString(), MyButtonIndex) Then
            Select Case MyButtonIndex
                Case 1:
                    ' Little instruction
                Case 2:
                    ' Call a bigger method, with newer parameters
                    Call HandleMainFormButton1(MyButton, "Houston we have a problem !")

                ' ...
                Case 300:
                    Call HandleMainFormButton300("Just kidding..!")
                Case Else
                    ' This is NOT an indexed Button.
                    MessageBox.Show("You've forgotten to handle button " + MyButtonIndex.ToString())
            End Select
        End If
    End If
End Sub

^^ CRAZY! Более 300 проверок для кнопки № 300 ... Не забудьте добавить обработчики для 300 кнопок ...

AddHandler Button1.Click, AddressOf HandleButtonClick
AddHandler Button2.Click, AddressOf HandleButtonClick
AddHandler Button3.Click, AddressOf HandleButtonClick
' ...
AddHandler Button299.Click, AddressOf HandleButtonClick
AddHandler Button300.Click, AddressOf HandleButtonClick
1 голос
/ 23 мая 2013

Я еще попробую эту идею:

А как насчет Button1.Click уже обрабатывается в Form1?

Хорошо, посмотрите на этот кусок кода:

Public Partial Class Form1
    Private Sub Button1Click(sender As Object, e As EventArgs) Handles Button1.Click
        MessageBox.Show("Form1 : " + Button1.Text)
    End Sub

    Public Sub New()
        Me.InitializeComponent()
    End Sub
End Class

Public Class Form1Handler
    Inherits Form1

    Private Sub HandleForm1HandlerButton1Click(sender As Object, e As EventArgs)
        MessageBox.Show("Form1Handler : " + Button1.Text)
    End Sub

    Private Sub AddHandlersToButtonClick()
        AddHandler Button1.Click, AddressOf HandleForm1HandlerButton1Click
    End Sub

    Private Sub OnMainFormHandlerLoad() Handles Me.Load
        AddHandlersToButtonClick()
    End Sub
End Class

Когда вы нажимаете кнопку 1 в форме 1, у вас появляется одно диалоговое окно:

MainForm: это Button1 [OK]

Но когда вы нажимаете кнопку 1 в Form1Handler, у вас появляется ДВА диалога:

Первый: Форма 1: Это Кнопка1 [ОК]

Тогда: Form1Handler: Это Button1 [OK]

Обходной путь, если вы хотите избавиться от Обработчиков в Form1:

Обходной путь 1 :

Изменения в Form1 Private Sub Button1Нажмите (...) на Public .

    Public Sub Button1Click(sender As Object, e As EventArgs) Handles Button1.Click

Затем добавьте удаление обработчика в Form1Handler:

    Private Sub AddHandlersToButtonClick()
        RemoveHandler Button1.Click, AddressOf Button1Click
        AddHandler Button1.Click, AddressOf HandleForm1HandlerButton1Click
    End Sub

Это поможет, удалив вызов Button1Click (...) в Form1 из метода Form1Handler.

Обходной путь 2 : (и это мой выбор)

Если вам нужно установить обработчик щелчка для кнопки 1 в форме Form1, измените его состояние Приватный на Защищенный перезаписываемый .

Public Partial Class Form1
    Protected Overridable Sub Button1Click(sender As Object, e As EventArgs) Handles Button1.Click
        MessageBox.Show("Form1 : " + Button1.Text)
    End Sub
    ' ...
End Class

А это ваш класс Form1Handler:

Public Class Form1Handler
    Inherits Form1

    Protected Overrides Sub Button1Click(sender As Object, e As EventArgs)
        MessageBox.Show("Form1Handler : " + Button1.Text)
    End Sub
End Class

Нет необходимости использовать AddHandlersToButtonClick ().

Нет необходимости использовать HandleForm1HandlerButton1Click ().

С ключевым словом Переопределяет , вы просто переопределяете каждый метод Button1Click, Button2Click, ..., Button300Click; предполагая, что ваша цель - создать кучу совершенно новых инструкций в Form1Handler ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...