Visual Studio - Affect all textboxes at once - vb.net

I am trying to remove leading zeroes from my textboxes. I have the code working, but I have close to 50 textboxes. I don't really want to have to make 50 textbox.TextChanged events.
Is there anyway to affect all of the textboxes with the same code?
This is the code I am using:
Private Sub txtTier1_100_TextChanged(sender As Object, e As EventArgs) Handles txtTier1_100.TextChanged
txtTier1_100.Text = txtTier1_100.Text.TrimStart("0"c)
End Sub

First step is to define a general purpose handler
Private Sub HandleTextChanged(sender As Object, e As EventArgs)
Dim tb = CType(sender, TextBox)
tb.Text = tb.Text.TrimStart("0"c)
End Sub
Then attach every one of your TextBox instances to this single handler
AddHandler txtTier1_100.TextChanged, AddressOf HandleTextChanged
AddHandler txtTier1_101.TextChanged, AddressOf HandleTextChanged
AddHandler txtTier1_102.TextChanged, AddressOf HandleTextChanged
Note that if you had all of the TextBox instances in a collection this could be done with a For Each loop as well
ForEach tb in textBoxList
AddHandler tb.TextChanged, AddressOf HandleTextChanged
Next

Private Sub txtTier1_100_TextChanged(sender As Object, e As EventArgs) Handles txtTier1_100.TextChanged, txtTier1_101.TextChanged, txtTier1_102.TextChanged...
'sender is the right textbox
End Sub

Related

Why doesn't Me.Controls.OfType work in VB.NET?

I'm using .NET Framework 4.7.2 for reference.
I'm using Me.Controls.OfType for automated handles in an event in my form.
Sub AddTextBoxes_TextChanged()
Dim textboxes = Me.Controls.OfType(Of TextBox)()
Console.WriteLine(textboxes.Count)
For Each txt In textboxes
AddHandler txt.TextChanged, AddressOf AllTextBoxes_TextChanged
Next
End Sub
Private Sub SampleForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddTextBoxes_TextChanged()
End Sub
Private Sub AllTextBoxes_TextChanged(sender As Object, e As EventArgs)
' ...
End Sub
However, the For loop doesn't work, so I checked if there are actual textbox controls within textboxes with Console.WriteLine(textboxes.Count). Well, the result is 0. I've checked multiple times in the Form Design for textboxes, and they exist. Why doesn't Controls.OfType(Of TextBox)() work?
Place your handler in the code for the form.
In design view select the one of the text boxes.
In the Properties window select the lightning bolt to display all the events available for a TextBox. Choose the TextChanged event and the drop down box arrow. Your AllTextBoxes_TextChanged method will be listed because the signature matches. Select your method and the Handles code will be added to the method.
Do the same for each text box you wish to use this method.
Of course you can always type the extended Handles clause.
However, I don't see what is wrong with your code.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim textboxes = Controls.OfType(Of TextBox)() '.ToList
For Each txt In textboxes
AddHandler txt.TextChanged, AddressOf AllTextBoxes_TextChanged
Next
End Sub
Private Sub AllTextBoxes_TextChanged(sender As Object, e As EventArgs)
Dim tb = DirectCast(sender, TextBox)
MessageBox.Show($"The text changed event fired by {tb.Name}")
End Sub
Works for me.

Is there a way to simplify this code? Visual Basic Here

I'm a newbie to Visual Basic and I have this code over here that's been bugging me. I can't think of another way to simplify this. Can you please help? Thanks!:
Private Sub PictureBox_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click,
PictureBox2.Click, PictureBox3.Click, PictureBox4.Click, PictureBox5.Click, PictureBox6.Click,
PictureBox7.Click, PictureBox8.Click, PictureBox9.Click, PictureBox10.Click, PictureBox11.Click,
PictureBox12.Click, PictureBox13.Click, PictureBox14.Click, PictureBox15.Click, PictureBox16.Click,
PictureBox17.Click, PictureBox18.Click, PictureBox19.Click, PictureBox20.Click, PictureBox21.Click,
PictureBox22.Click, PictureBox23.Click, PictureBox24.Click, PictureBox25.Click, PictureBox26.Click,
PictureBox27.Click, PictureBox28.Click, PictureBox29.Click, PictureBox30.Click, PictureBox31.Click,
PictureBox32.Click, PictureBox33.Click, PictureBox34.Click, PictureBox35.Click, PictureBox36.Click,
PictureBox37.Click, PictureBox38.Click, PictureBox39.Click, PictureBox40.Click, PictureBox41.Click,
PictureBox42.Click, PictureBox43.Click, PictureBox44.Click, PictureBox45.Click, PictureBox46.Click,
PictureBox47.Click, PictureBox48.Click, PictureBox49.Click, PictureBox50.Click, PictureBox51.Click,
PictureBox52.Click, PictureBox53.Click, PictureBox54.Click, PictureBox55.Click, PictureBox56.Click,
PictureBox57.Click, PictureBox58.Click, PictureBox59.Click, PictureBox60.Click, PictureBox61.Click,
PictureBox62.Click, PictureBox63.Click, PictureBox64.Click
...............
............... (stuff is down here.)
...............
...............
End Sub
You will need to store the lists in a collection of some sort. This can either be an array or a List(Of PictureBox) or if all of the controls have the same parent you can simply leverage the Controls property.
Once you have the collection in place, you will need to iterate over collection and use AddHandler to reference. Inside the referenced method, you would get the sender, and convert it to a PictureBox.
Here is an example assuming all the PictureBox controls are on the Form:
Private Sub Form1_Load(sender As Object, e As EventArgs)
For Each pb In Controls.OfType(Of PictureBox)()
AddHandler pb.Click, AddressOf pb_Click
Next
End Sub
Private Sub pb_Click(sender As Object, e As EventArgs)
Dim pb = DirectCast(sender, PictureBox)
' pb is the control that was clicked
End Sub
Here's how to build a list of the pictureboxes, with them "in order", assuming they are already on the form:
Public Class Form1
Private PBs As New List(Of PictureBox)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i As Integer = 1 To 64
Dim ctlName As String = "PictureBox" & i
Dim ctl As Control = Me.Controls.Find(ctlName, True).FirstOrDefault
If Not IsNothing(ctl) AndAlso TypeOf ctl Is PictureBox Then
Dim pb As PictureBox = DirectCast(ctl, PictureBox)
AddHandler pb.Click, AddressOf PB_Click
PBs.Add(pb)
Else
MessageBox.Show("Unable to find " & ctlName)
End If
Next
End Sub
Private Sub PB_Click(sender As Object, e As EventArgs)
Dim pb As PictureBox = DirectCast(sender, PictureBox)
' ... do something with pb ...
End Sub
End Class
From the comments:
Wait a minute, how do I do For Each pb In Controls.OfType(Of
PictureBox)() AddHandler pb.Click, AddressOf pb_Click Next But for a
List(Of Picturebox) named "Formula"?
For Each pb As PictureBox in Formula
AddHandler pb.Click, AddressOf pb_Click
Next
Here's what you code produces after turning on the BorderStyle:

VB.NET - How to add a large amount of events to a single handle?

Recently I've been working on a program that has a few TextBoxes, CheckBoxes, ComboBoxes, etc., and I found that making one function handle multiple events is pretty simple, you just separate the events with a comma and the code recognizes the inidvidual events.
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click, Button2.Click
MsgBox("Hello World!")
End Sub
However, when you start to have a large number of events that you want handled by the same function, it gets a bit messy.
Private Sub Checks_CheckedChanged(sender As Object, e As EventArgs) Handles chkInput1.CheckedChanged, chkInput2.CheckedChanged, chkInput3.CheckedChanged, chkInput4.CheckedChanged, checkInput5.CheckedChanged, chkOutput.CheckedChanged
MsgBox("Checks Changed!")
End Sub
You can use the line continuation character _ to make it look a little better.
Private Sub Checks_CheckedChanged(sender As Object, e As EventArgs) Handles _
chkInput1.CheckedChanged, chkInput2.CheckedChanged, chkInput3.CheckedChanged, _
chkInput4.CheckedChanged, checkInput5.CheckedChanged, chkOutput.CheckedChanged
MsgBox("Checks Changed!")
End Sub
But you still end up with a nasty block of text. Is there a more clean/concise way of doing this? What I have in mind is that it would be really nice to give an array of object events as an argument but I don't think that's possible.
You could do this by using the
AddHandler ObjectName.EventName, AddressOf EventHandlerName
syntax
It's simple enough to write a Sub that takes an array of object and loops over them to add the handler for each event.
For checkboxes:
Public Sub AddHandlerSub(PassedArray As CheckBox())
For Each item As CheckBox in PassedArray
AddHandler Item.CheckedChanged, AddressOf EventHandlerName
next
End Sub
You can simply iterate the controls in the controls collection and not fuss with an array at all. You can also do further conditions if you want to exclude/add any given control, such as in the example of the TextBox Case in the following example.
Private Sub DataTables_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each Ctrl As Control In Panel1.Controls
Select Case Ctrl.GetType
Case GetType(CheckBox)
AddHandler DirectCast(Ctrl, CheckBox).CheckedChanged, Sub(S As Object, EA As EventArgs)
Dim ChkBox As CheckBox = DirectCast(S, CheckBox)
'do something with ChkBox
End Sub
Case GetType(TextBox)
Select Case Ctrl.Name
Case "TextBox1", "TextBox2" 'Add handle only to these contrls
'Or you could add Case Else and put the below handle within it
'Then this becomes an exclusion case
AddHandler DirectCast(Ctrl, TextBox).TextChanged, Sub(S As Object, EA As EventArgs)
Dim TxtBox As TextBox = DirectCast(S, TextBox)
'do something with TxtBox
End Sub
End Select
End Select
Next
End Sub
Additional Information: You can select procedures as Event Handlers by selecting the control. Then in the Properties window click the lightning bolt to display Events. Selected the event you wish to assign a handler and then the drop down arrow to the right. The resulting list will display all the Subs that match the signature of that event. Select the one you want and the designer will write or append the control to the Handles clause.
Add a procedure to the Form with a signature that matches the event.
Private Sub MultipleButtons(sender As Object, e As EventArgs)
End Sub
In the dropdown the list contains all Subs that match the signature of the event.
The designer writes the Handles clause
Private Sub MultipleButtons(sender As Object, e As EventArgs) Handles Button5.Click
End Sub

dynamically create a new tab with textbox, button in the tab with click and keypress events (AddHandler is what i cant get to work)

I am creating some tabs and I need two things to work that I can't get to work. I need to AddHandler for a Textbox.Keypress event AND a Button.Click event. I can make these things work outside of the tabcontrol but not in.
In the example below my text box and buttons have same name from on tab to the another, I thought that might be my problem but even changing names between tabs does not work. I assume I need to be more specific in the AddHandler part to give the tab name as well as control. There is a logic in my real code to allow me to give unique names to each tab panel and controls, but i can't get the simple part to work.
I left some of the things I tried commented, but I tried LOTS and LOTS of other things.
Public Class Form1
Public Sub addTab(tabPageName As String)
Dim tabpage As New TabPage
tabpage.Text = tabPageName
tabpage.Name = "tabPage1" 'real code has logic to make sure names are unique
Dim label1 As New Label
Dim txtCreator As New TextBox
Dim combox1 As New ComboBox
Dim tabPageButton2 As New Button
tabPageButton2.Parent = tabpage
label1.Parent = tabpage
txtCreator.Parent = tabpage
combox1.Parent = tabpage
label1.Location = New Point(10, 10)
txtCreator.Location = New Point(150, 10)
combox1.Location = New Point(300, 10)
tabPageButton2.Location = New Point(20, 40)
label1.Text = "Creator"
txtCreator.Name = "txtCreator"
'fill the comboboxes...this will come from a database but testing now.
combox1.Items.Add("one")
combox1.Items.Add("two")
combox1.Items.Add("three") 'ok that works so should work from DB no problem.
tabRoleClass.TabPages.Add(tabpage)
End Sub
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
addTab("First Tab")
AddHandler Controls("tabRoleClass.tabPage1.tabPageButton2").Click, AddressOf tabPageButton_click
'AddHandler CType(Controls("tabPageButton"), Button).Click, AddressOf tabPageButton_click
'AddHandler Controls("tabPageButton").Click, AddressOf tabPageButton_click
AddHandler CType(Controls("txtCreator"), TextBox).KeyPress, AddressOf txtcreator_keypress 'the Keypress to call lookup
End Sub
Private Sub tabPageButton_click(sender As System.Object, e As System.EventArgs) 'Handles tabPageButton.click
MessageBox.Show(tabRoleClass.SelectedTab.Name.ToString)
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
addTab("Second Tab")
tabRoleClass.SelectedIndex = tabRoleClass.TabCount - 1
'AddHandler Controls("tabRoleClass.tabPage1.tabPageButton2").Click, AddressOf tabPageButton_click
'AddHandler CType(Controls("tabPageButton"), Button).Click, AddressOf tabPageButton_click
'AddHandler Controls("tabPageButton").Click, AddressOf tabPageButton_click
'AddHandler CType(Controls("txtCreator"), TextBox).KeyPress, AddressOf txtcreator_keypress 'the Keypress to call lookup
End Sub
Private Sub txtcreator_keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) 'Handles txtCreator.KeyPress
MessageBox.Show("keypress worked on " & tabRoleClass.SelectedTab.Name.ToString)
End Sub
End Class
This is a very confusing question and your code could really do with some cleaning, but you need to add the AddHandler code to the addTab subroutine as pointed out by #Plutonix:
Public Sub addTab(tabPageName As String)
Dim tabpage As New TabPage
Dim tabPageButton As New Button
Dim txtCreator As New TextBox
/.../
AddHandler tabPageButton.Click, AddressOf tabPageButton_click
AddHandler txtCreator.KeyDown, AddressOf txtcreator_keypress
tabRoleClass.TabPages.Add(tabpage)
End Sub
Private Sub tabPageButton_click()
MessageBox.Show(tabRoleClass.SelectedTab.Name.ToString)
End Sub
Private Sub txtcreator_keypress()
MessageBox.Show("keypress worked on " & tabRoleClass.SelectedTab.Name.ToString)
End Sub
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
addTab("First Tab")
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
addTab("Second Tab")
tabRoleClass.SelectedIndex = tabRoleClass.TabCount - 1
End Sub
AddHandler works by adding event handlers to your controls. This means that each time an event is raised during this runtime, the new event handler will handle the event; everytime you click your tabPageButton the associated event tabPageButton_click will handle it.
Therefore, you will only need to add the handler once, preferably upon the creation of the control. There is absolutely no need to create them upon every single keypress, for example. You should look up event handlers on MSDN.
Hope this helps!
Sorry if the code was confusing, I cut up my actual code to make a "sample" and I can see the confusion. Now of course I AM confused, I originally had the AddHandler INSIDE the addTab sub that creates the tab and it didn't work there, I incorrectly assumed the reason was that the control was not yet created so I moved it out. Moving it back in this sub this morning worked perfectly, I don't know what I did wrong but its working GREAT by moving it up to where it belongs, thanks A LOT, I worked on this for 2 days trying and googling things. Next time I will post real code instead of a sample to be less confusing and also remove my commented attemps (I thought those would help show what I was trying but I think it didn't)

Check if mouse pointer enteres panel components

How do I check if my mouse cursor enters any component in a panel .
I stared to write this code to check when the mouse enters any check box in my panel then I realised that I had no idea how to actually check if the mouse enters the components I the panel .
Private Sub GenCheck()
For Each CheckBox In datapanel1.Controls
Next
End Sub
how do i go about doing this ?
Edit
I have an Idea but i'm not too sure about it
I could say
Private Sub GenCheck()
Dim cb As CheckBox
For Each cb In datapanel1.Controls
AddHandler cb.MouseEnter, AddressOf cb_MouseEnter
AddHandler cb.MouseLeave, AddressOf cb_MouseLeave
Next
End Sub
Private Sub cb_MouseEnter(sender As Object, e As EventArgs)
End Sub
Private Sub cb_MouseLeave(sender As Object, e As EventArgs)
End Sub
You can use MouseHover to determine when the cursor hovers above the checkbox like this.
Private Sub CheckBox1_MouseHover(sender As Object, e As System.EventArgs) Handles CheckBox1.MouseHover
MsgBox("Mouse over!")
End Sub`
Edit:
I have put a panel on a form with two checkboxes to mimic your requirements, here is what you're looking for:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
For Each pnlCheckBox As CheckBox In Panel1.Controls
AddHandler pnlCheckBox.MouseHover, AddressOf Me.CheckBoxMouseOver
Next
End Sub
Private Sub CheckBoxMouseOver()
MsgBox("Mouse over!")
End Sub
*PERFECT WAY TO ACCOMPLISH THIS *
Dim con As Control
For Each con In datapanel1.Controls
AddHandler con.MouseEnter, AddressOf con_MouseEnter
AddHandler con.MouseLeave, AddressOf con_MouseLeave
Next
End Sub
Private Sub con_MouseEnter(sender As Object, e As EventArgs)
'DO SOMETHING'
End Sub
Private Sub con_MouseLeave(sender As Object, e As EventArgs)
'DO SOMETHING'
End Sub