I am kinda new to visual basic and was wondering if it is possible to trigger events in a class, based on action with in form.
So the following is my problem:
I have a form called Main, with a picture box called picPID
And a class called add_new
What I want to do is:
when the right mousebutton is clicked, the code for the event handling is placed within the class called add_new
I thought i could just declare it in the following way:
Sub meMouseDown(sender As Object, e As MouseEventArgs) Handles Main.picPID.MouseDown
But I get an error saying i have to declare it withEvents, I tried to declare the picturebox as:
Public shared withEvents as picturebox
but it dident help, any sugestions? It is not a problem having the code within the Main form, but it would result in a lot of code, so I was hoping to split it up.
So you have the class with an eventhandler:
Public Class add_new
Public Sub PictureBoxEventHandler(sender As Object, e As MouseEventArgs)
'Your Implementation
End Sub
End Class
Then you need an instance of this class within the form containing the picturebox:
Public Class Form1
Private add_New_Command As New add_new ' hold a reference to the command
'constructor
Public Sub New()
InitializeComponent()
' and add the handler to the event of the picture box ... hook it up
AddHandler PictureBox1.MouseDown, AddressOf add_New_Command.PictureBoxEventHandler
End Sub
End Class
Related
I'm relatively new to Windows Forms development and my first real application has reached a point where a lot of code starts to build up in my main Form file, so I decided to restructure my project using the MVC pattern.
One major problem I have is dealing with the different control events of the form. I have several buttons, textfields, comboboxes and also a tabcontroll element which again contains different input elements and so far, every procedure for handling clicks, updates and other changes is defined in my main class.
For example:
Private Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click
some code...
End Sub
So my question is: what would be the best way to handle these events outside of my main form? I'm more familiar with building GUIs in Java where you can use ActionListeners to achieve this but I have found nothing similar for my work with Windows Forms.
To subscribe to a Control event outside of your main form class, make your control public, so you can access from another class). This can be done using the Modifier property at design-time. Then, use the AddHandler keyword to subscribe to any event programmatically.
After researching a bit more, I found that there is probably not THE correct answer to this problem but I found 2 approaches which provide a solution in the way I was looking for. In both cases, I use a controller class which is responsible for handling any user interaction from my main form.
The first approach makes use of what DmitryBabich suggested, adding a handler to the object and referencing it to a method of my controller class:
in Form1:
Dim ctrl as new Controller(Me)
AddHandler Button1.Click, AddressOf ctrl.doSomething
Controller class:
Public Class Controller
Private myForm As Form1
Public Sub New(ByVal f As Form1)
myForm = f
End Sub
Public Sub doSomething(sender As Object, e As EventArgs)
MsgBox("Button clicked.")
End Sub
End Class
For an example this simple it is not necessary to pass an instance of Form1 over to the controller but if for example I'd like to access the values of other control elements as well, I can address them by using this instance of Form1.
For example:
Public Sub doSomething(sender As Object, e As EventArgs)
MsgBox("You clicked the button, by the way: The value of TextField1 is " & myForm.TextField1.text)
End Sub
The other approach is almost identical except that here the controller knows all the relevant user control objects of the form and can handle their events directly, meaning that in the main form I have to do nothing more than create an instance of the controller. In the controller however, I have to assign every user control I want to access to its own variable as soon as the main form is loaded:
in Form1:
Dim ctrl as new Controller(Me)
Controller class:
Public Class Controller
WithEvents myForm As Form1
WithEvents button1 As Button
WithEvents button2 As Button
Public Sub New(ByVal f As Form1)
myForm = f
End Sub
Public Sub formLoad() Handles myForm.Load
button1 = myForm.Button1
button2 = myForm.Button2
End Sub
Private Sub b1Click() Handles button1.Click
MsgBox("You clicked button1!")
End Sub
Private Sub b2Click() Handles button2.Click
MsgBox("Button #2 was clicked!")
End Sub
End Class
I have a little problem here. I'm trying to transfer/pass/raise the events of an owned form to his parent. Lets look at my example:
Lets say i have a form that initialize a CustomPanel (simply a class that inherits from System.Windows.Forms.Panel). It also have an event handler (it could be an other event, not necessarily a click event):
Public Sub New()
Me.Size = New Size(1000,1000)
Dim pnl1 As New CustomPanel()
pnl1.Location = New Point(0,0)
pnl1.size = New Size(100,100)
Me.Controls.Add(pnl1)
End Sub
Private Sub form1_Click(sender As Object, e As EventArgs) Handles Me.Click
MsgBox("I got it!")
End Sub
I did something similar and when I clicked on the CustomPanel (pnl1) the parent container (form1) did not receive a click event ... which is understandable. I tried to look in the properties of the CustomPanel (pnl1) if i could find something interesting like "click through" or "raise event to parent" (I was desperate here) but without success. I said alright, I will handle the events that I need to pass to parent in the CustomPanel class but I cant find a solution here neither:
Imports System.Windows.Forms
Public Class CustomPanel
Inherits Panel
Public Sub New()
End Sub
Private Sub CustomPanel_Click(sender As Object, e As EventArgs) Handles Me.Click
'What to put here?
'Me.Parent.?
End Sub
End Class
I just want to know if its possible to throw/raise/pass events to the parent. One thing is sure, its that i shouldn't have to and i cannot add anything else to the parent form. The reason is simple, i could have over 100 controls in this parent form and they could be added dynamically. And on top of that, these controls could also have their own controls inside! So i could have something like:
pnl99 call parent click -> pnl98 call parent click -> ... until the parent of the control really handle the click event ... -> form1 perform click event
Maybe its hard to understand but if you can help me I would appreciate.
Using a custom event, that the form owning the panel subscribes to. Raise Event
Public Sub New()
Me.Size = New Size(1000,1000)
Dim pnl1 As New CustomPanel()
pnl1.Location = New Point(0,0)
pnl1.size = New Size(100,100)
Addhandler pnl1.MyClickEvent, AddressOf pl_Click
Me.Controls.Add(pnl1)
End Sub
Private Sub pl_Click()
MsgBox("I got it!")
End Sub
Custom panel:
Public Class CustomPanel
Inherits Panel
Public Event MyClickEvent
Private Sub CustomPanel_Click(sender As Object, e As EventArgs) Handles Me.Click
RaiseEvent MyClickEvent()
End Sub
End Class
On the child form
Imports System.Windows.Forms
Imports STAS_PLC_Link_Lib
Public Class ChildForm
Public Event MyClick()
'.....rest of code
On the parent form
Public Class ParentForm
Private Sub GetSomeClick() Handles ChildFor.MyClick
System.Console.WriteLine("test")
End Sub
end Class
I hope I can make it clear what my problem is. I have made my own Chart control
Public Class MyChart
Inherits Chart
[...]
End Class
In this class I handle the MouseDown event of the chart and do stuff like zooming, dragging markers and so on.
In the project I am using the chart I also handle the MouseDown event to do some more specific stuff. Now there is this problem:
In the MouseDown event handler in the MyChart class I use the middle mouse button to drag the chart.
However in the project MouseDown event handler I check if the user hit a specific object and want to let him drag this object also with the middle mouse button. The problem is, that the handler in MyChart is executed first so I can't check if the user hit the object (and therefore initiate the dragging of this object).
What I need is that the event handler in the project is executed first and after this the one in MyChart.
To hopefully make it more clear:
(Dummy Code)
Public Class SomeProject
WithEvents Chart as MyChart
Public Sub Chart_MouseDown(sender as object, e as MouseEventArgs) Handles Chart.MouseDown
'This is executed second, but should be executed first.
End Sub
End Class
Public Class MyChart
Inherits Chart
Public Sub MyChart_MouseDown(sender as object, e as MouseEventArgs) Handles Me.MouseDown
'This is executed first, but should be executed second.
End Sub
End Class
Is there any way I can do this?
Try creating your own event:
Public Class MyChart
Inherits Chart
Public Event ChartMouseDown(sender As Object, e As MouseEventArgs)
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
RaiseEvent ChartMouseDown(Me, e)
MyBase.OnMouseDown(e)
// your second code here...
End Sub
End Class
Then your project code would look like this:
Public Class SomeProject
WithEvents Chart as MyChart
Public Sub Chart_ChartMouseDown(sender as object, e as MouseEventArgs) _
Handles Chart.ChartMouseDown
// your first code here...
End Sub
End Class
I need some help getting my head wrapped about instances and classes. In the code below I have a main_form, and I am also loading a user_control into the main_form. I have a property that resides inside main_form that I will be setting data called obj. My question is when I am doing work inside of the user_control, how can I reach in and set the obj property of main_form. I tried main_form.obj but I keep getting the error "object reference not set to an instance of an object". So, I'm not sure how to do it. Here's the dumbed down code
Public Class FormControlClass
Private _obj As New objCollection
Public Property obj As objCollection
Get
Return _obj
End Get
Set(ByVal value As objCollection)
_obj = value
End Set
End Property
'Load User Control Into Form from here.
me.controls.add('UserControl')
End Class
Public Class UserControlClass
'Access the obj property in the form control class from here.
FormControlClass.obj = 1
End Class
Even if you could do what you are trying to do, it would be a bad idea, because you would be coupling your user control to this particular form, making it useless outside of this form.
Instead you need to have your user control generate an event that the form can subscribe to and handle itself. In other words, you want to make the user control create a message that can be delivered to the form, like this:
Public Class UserControlClass
' Define event that will be raised by user control to anyone interested in handling the event
Public Event UC_Button1Click()
' Mechanism to allow event to be raised by user control
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RaiseEvent UC_Button1Click()
End Sub
End Class
Now in your form class, you need to add a handler for the event raised by the user control, like this:
AddHandler userControl1.UC_Button1Click, AddressOf Button1_Click
Finally, you would create the method that is referenced in the AddressOf syntax, like this:
Public Sub Button1_Click(ByVal sender As Object, ByVal args As EventArgs)
' Do something here
End Sub
Soon I asked for help to read properties of textbox which is inside usercontrol.
Accessing to control inside of usercontrol
As I have been suggested I make one very simple public class with name xTextBox and use it as textbox in my usercontrol. That work fine.
Public Class xTextBox
Inherits TextBox
End Class
Now I can simply read a property on that xTextbox from main program which contain that usercontrol:
Dim s As Integer = myUserControl.xTextBox1.SelectionStart
But now is a problem that I can't get events of that Textbox in main program.
Maybe I can declare 'Shadows Event TextChanged...' etc, but I will need more events in different situations where usercontrol would be, and intentionally raising every of them don't look elegant in mean of practical programming.
How to get events of those xTextbox to main program?
If the your new UserControl has only one control and Inherits TextBox, then you can just attach the events like normal, either with the Property Editor, or Manually with AddHandler. If things are more complicated than that I would probably create a panel and put your new TextBox's in it, then it will be a lot easier to access the events.
Public Class myUserControl
Inherits TextBox
End Class
Public Class Form1
Public Sub New()
InitializeComponent()
AddHandler MyUserControl1.TextChanged, AddressOf MyUserControl_textChanged
End Sub
Private Sub MyUserControl_textChanged(sender As Object, e As EventArgs)
Throw New NotImplementedException
End Sub
End Class
Or if your UserControl has Multiple Custom TextBox's in it, you can create a Custom Event and fire that in a common TextChanged Event on your UserControl and handle that in your Main Form.
Public Class UserControl1
Public Event TextChange(sender As Object, e As EventArgs)
Private Sub MyUserControl_TextChanged(sender As System.Object, e As System.EventArgs) Handles MyUserControl1.TextChanged, MyUserControl2.TextChanged
RaiseEvent TextChange(sender, e)
End Sub
End Class
Public Class Form1
Public Sub New()
InitializeComponent()
End Sub
Private Sub UserControl11_TextChange(sender As System.Object, e As System.EventArgs) Handles UserControl11.TextChange
MsgBox(CType(sender, TextBox).Name, MsgBoxStyle.Information)
End Sub
End Class