Here's my code:
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
I'm trying to get Form1Handler to process Form1's events automatically. How can I do this? Should I use a module instead? I'm doing this in Visual Basic 2010.
I don't want to have to make an event handler in Form1 and then pipe it to the other class / modu开发者_Go百科le. Is there some way to automatically "pipe" the events from form1 to form1handler?
If you need to handle a button or other control events outside the form class, you can make a user control to inherit the control, and then handle the events in the user control class. For example, this user control consists of an internal button control named 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
You can use it in the main form like this:
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
The click event is handled inside the mb class.
I realize that this thread is old, but I stumbled upon it in search of the answer to the same question. Hopefully this may help someone else. xpda's answer was good and does work, however it doesn't work with buttons created with the Form Designer, my solution does and is an alternative to xpda's method.
For this example I have Form1 with 2 buttons (Buttton1 and Button2) and a textbox (textbox1). I have also created a module (Module1). I have kept it simple and it should be easy to understand.
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
At the top of the Module you can have as many WithEvents that you need, one for each control. Keep in mind that every WithEvents you create should be followed by (in this example) with the event after the Handles clause in the MyButtons sub.
You must call the sub during the Form Load event or your program will not see the Module code. This is important to understand. If you have more than one sub, you must call them all.
Calling the Module from Form1 is as follows:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Module1.MyButtons(Nothing,Nothing)
End Sub
Once this is done, All click events from Button1 and Button2 will be handled in the Module. You can include other events for the Buttons in the Module or in the Form.
BTW, I should also add that you don't have to create a single sub to handle all events. In this example you could have created 2 subs, one for each button. Also, the name of the sub will never be called so it doesn't matter what you call it. The Button Click events will automatically be handled by the Module as if you wrote it in the Form code.
One more thing...
Another option is to create a Module with a subroutine that you want to handle the Button.Click and then from the Form menu use the AddHandler clause.
Module Module1
Public Sub MySub()
Form1.TextBox1.Text = "Button Clicked"
End Sub
End Module
The Form Code would look like this...
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
AddHandler Button1.Click, AddressOf Module1.MySub
End Sub
Using this method requires a different Sub for every button.click event since you want each button to do different things.
Well, that's 3 ways of doing the same thing, each with it's own strengths and weaknesses.
I always think that a good answer is the answer that tells how, exactly, we could handle Form1.Button1.Click (or whatever) in Form1Handler.
You could make your controls in Form1 as Protected, at least, instead of Private.
How?
In Form1.Designer.vb: At the end of the code, you should have:
Public Partial Class Form1
' ...
Private Button2 As System.Windows.Forms.Button
Private Button1 As System.Windows.Forms.Button
End Class
^^ Then change Private to Protected...
Protected WithEvents Button2 As System.Windows.Forms.Button
Protected WithEvents Button1 As System.Windows.Forms.Button
Then add WithEvents to ensure your buttons are declared with events.
Or in your IDE designer (Visual Studio 2010 or SharpDevelop) select your button, and in the properties tab, sets its Modifiers property (list) to "Protected". That will change its declaration in Form1.Designer.vb. I know that won't add "WithEvents".
Now, you can create Form1Handler that inherits from Form1.
How do I add an event handler in your Form1Handler?
First create a method that should handle your Button click, in your Form1Handler Class.
Private Sub HandleButtonClick(sender As Object, e As EventArgs)
' Instructions for Clicks goes here...
End Sub
Then create a method that ties Button clicks to the method above
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
Last, in your Form1Handler Class, add a call to the previous method upon loading:
Private Sub OnForm1Handler_Load() Handles Me.Load
AddHandlersToButtonClick()
End Sub
Now, when you load your Form1Handler that inherits from Form1, HandleButtonClick(..) is launched each time you click on Button1 or Button2. Now, you may want to do something different when you click on Button3 and when your mouse enters Panel1... It's the same:
' 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
Then what if you have 300 buttons to handle?
Okay! If, like me, you are a lazy man, and you just want to do litte things for some buttons, and call bigger methods for others, you could use the Tag Property of your Button in the IDE:
- For Button1 -> Tag = 1
- For Button2 -> Tag = 2
- ...
- For Button300 -> Tag = 300
Then, just use the method provided above, and add a Tag Property check, with something like:
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+ checks to do for Button number 300... Don't forget to add handlers for your 300 buttons...
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
I'll give more trial to the idea:
What about Button1.Click already handled in Form1?
Well, look at this piece of code:
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
When you click on Button1 in Form1, you have one dialog box:
MainForm: This is Button1 [OK]
But when you click on Button1 in Form1Handler, you have TWO dialogs:
First: Form1: This is Button1 [OK]
Then: Form1Handler: This is Button1 [OK]
Workaround if you want to get rid of Handlers in Form1:
Workaround 1:
Changes in Form1 Private Sub Button1Click(...) to Public.
Public Sub Button1Click(sender As Object, e As EventArgs) Handles Button1.Click
Then add an Handler removal in Form1Handler:
Private Sub AddHandlersToButtonClick()
RemoveHandler Button1.Click, AddressOf Button1Click
AddHandler Button1.Click, AddressOf HandleForm1HandlerButton1Click
End Sub
This will do the trick, by removing the call to Button1Click(...) in Form1 from a method of Form1Handler.
Workaround 2: (and that's my choice)
If only you have to set a click handler for Button1 in Form1, change its Private state to Protected Overridable.
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
And this is your Form1Handler class:
Public Class Form1Handler
Inherits Form1
Protected Overrides Sub Button1Click(sender As Object, e As EventArgs)
MessageBox.Show("Form1Handler : " + Button1.Text)
End Sub
End Class
There is no need to use AddHandlersToButtonClick().
There is no need to use HandleForm1HandlerButton1Click().
With the keyword Overrides, you just redefine each Button1Click, Button2Click, ..., Button300Click methods; assuming your goal is to create a bunch of whole new instructions in Form1Handler...
精彩评论