Detecting the ID of checkbox that was checked - vb.net

I am making a windows form application. I want to detect which checkbox is being selected by the user. One way to check this would be to loop through all the controls everytime a checkbox checkchanged event is fired. But I do not want to do that because multiple checkboxes could be checked. I want to get the ID of checkbox as it is selected or on a mousedown event. How can I do so?

You can add the event handlers for the checkboxes you want at runtime. Use the Where clause to filter by name if applicable. This code does it in form_load.
Inside the handler, you can cast sender to a local variable which represents the checkbox which was checked, if you want.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each checkBox In Me.Controls.OfType(Of CheckBox)().Where(Function(cb As CheckBox) cb.Name.Contains("CheckBox"))
AddHandler checkBox.CheckedChanged, AddressOf checkboxCheckedChanged
Next
End Sub
Private Sub checkboxCheckedChanged(sender As Object, e As EventArgs)
Dim myCheckbox As CheckBox = DirectCast(sender, CheckBox)
Dim c As Boolean = myCheckbox.Checked
Dim n As String = myCheckbox.Name
' etc.
End Sub
EDIT
As Neolisk pointed out, this doesn't account for nested controls, i.e. controls inside containers on the form. This extension method returns all those controls:
<Extension()> _
Public Function ChildControls(Of T As Control)(ByVal parent As Control) As List(Of T)
Dim result As New List(Of Control)
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is T Then result.Add(ctrl)
result.AddRange(ctrl.ChildControls(Of T)())
Next
Return result.ToArray().Select(Of T)(Function(arg1) CType(arg1, T)).ToList()
End Function
And make this the loop in form_load instead:
For Each checkBox In Me.ChildControls(Of CheckBox).Where(Function(cb As CheckBox) cb.Name.Contains("CheckBox"))
AddHandler checkBox.CheckedChanged, AddressOf checkboxCheckedChanged
Next

Use sender argument in the event handler.
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) _
Handles CheckBox1.CheckedChanged
'DirectCast(sender, CheckBox).Name ?
End Sub

Related

Clear focused textbox in multiple textboxes in vb.net using delete key

I want a good example of clearing focused textbox among multiple textboxes using delete key. Please help me providing vb.net code.
The public sub is as such :
Public Sub EmptyTxt(ByVal Frm As Form)
Dim Ctl As Control
For Each Ctl In Frm.Controls
'If TypeOf Ctl Is TextBox Then Ctl.Text = ""
Next
End Sub
Then I call this sub from delete keydown event. But it clears all textboxes rather than clearing the focused one.
There's an easier way to do that.
Simply assign all the textbox keyDown events to the same handler. In that handler, cast sender to a textbox and clear it.
Private Sub Form1_Load (sender As Object, e As EventArgs) Handles MyBase.Load
For Each tb As TextBox In Controls.OfType(Of TextBox)
AddHandler tb.KeyDown, AddressOf TbKeyDown
Next
End Sub
Private Sub TbKeyDown (sender As Object, e As KeyEventArgs)
Dim tb = CType(sender, TextBox)
If e.KeyCode = Keys.Delete Then
tb.Clear()
End If
End Sub

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

Removing and adding event handlers for different ComboBoxes where the ComboBox is passed as a parameter

I have a method that takes a ComboBox as a parameter and then adds data to it. When data is added, the SelectedIndexChangedEvent fires. Is there a way that, in the called method, I can remove the above event handler for whatever ComboBox is passed as a parameter and then add is at the end of the method? I know how to remove and add specific handlers, but can't figure out how to do it based on which ComboBox is passed.
Here's the method..
Private Sub PopulateComboBox(ByRef cboBox As ComboBox, ByVal itemSource As String)
'Remove handler for cboBox
'Do stuff that would otherwise cause the event handler to execute
'Add handler for cboBox
End Sub
I have 4 ComboBoxes - would it just be easier to remove all 4 event handlers and then add them again at the end of the code? I would however like to know if this is possible so that I can possibly apply to re-usable code in the future
The most basic way to go about this is to do this:
Private Sub PopulateComboBox(ByRef cboBox As ComboBox, ByVal itemSource As String)
RemoveHandler cboBox.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged
'Do stuff that would otherwise cause the event handler to execute
AddHandler cboBox.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
End Sub
Another option, which might be better in some circumstances, is to do this:
Private _ignoreComboBox As ComboBox = Nothing
Private Sub PopulateComboBox(ByRef cboBox As ComboBox, ByVal itemSource As String)
_ignoreComboBox = cboBox
'Do stuff that would otherwise cause the event handler to execute
_ignoreComboBox = Nothing
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If sender Is Not _ignoreComboBox Then
End If
End Sub
Or, to handle multiple combo boxes at the same time:
Private _ignoreComboBoxes As List(Of ComboBox) = New List(Of ComboBox)()
Private Sub PopulateComboBox(ByRef cboBox As ComboBox, ByVal itemSource As String)
_ignoreComboBoxes.Add(cboBox)
'Do stuff that would otherwise cause the event handler to execute
_ignoreComboBoxes.Remove(cboBox)
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If Not _ignoreComboBoxes.Contains(DirectCast(sender, ComboBox)) Then
End If
End Sub
Here is one way:
' these happen to map to the same event handler
Private cb1Event As EventHandler = AddressOf cbx_SelectedIndexChanged
Private cb2Event As EventHandler = AddressOf cbx_SelectedIndexChanged
Then when used:
PopulateComboBox(cb1, items, cb1Event)
PopulateComboBox(cb2, items, cb2Event)
' or
PopulateComboBox(cb3, items, AddressOf cbx_SelectedIndexChanged)
The method would be declared:
Private Sub PopulateComboBox(cboBox As ComboBox,
items As String, ev As EventHandler)
Personally, since you know the cbo involved anyway, I'd do that before the call:
RemoveHandler cb1.SelectedIndexChanged, AddressOf cbx_SelectedIndexChanged
PopulateComboBox(cb1, items)
AddHandler cb1.SelectedIndexChanged, AddressOf cbx_SelectedIndexChanged
There is not much to be gained by passing all the info to do something to something else so it can do what you know needs to be done.

VB Uncheck all checked checkboxes in forms

This is my form1, it contains lots of checkboxes and a button, to show the form2:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.show()
End Sub
End Class
And here is my form2, also it contains lot of checkboxes and a button, for unchecking all the checkboxes on form1 and on form2:
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'code for clearing all the checkboxes, I don't know how to do it
End Sub
End Class
My question is: how can I make a code in Form2.Button1 for unchecking all the checkboxes in the Form1, Form2 and even other forms??
I tried this code, that unchecks only the checkboxes in the form where is it placed:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each cc As Control In Me.Controls
If TypeOf cc Is CheckBox Then
DirectCast(cc, CheckBox).Checked = False
End If
Next
End Sub
Maybe I can do that by editing this code.. I don't know
Thank you all in advance
You need to keep a list of open forms in a central location, when any form is created it should add itself to the list and when disposed, remove itself (you can inherit all your forms from a common base form that does this)
Then you can give all forms to a similar method that iterates through them and does the job.
Also, please note that your code does not uncheck all checkboxes on the form, it just unchecks checkboxes Directly on the form. If you might have chackboxes on panels, groupboxes, etc, you need to improve the code to recursively check for inner controls.
Likely #Alireza said you need to recursive check for inner controls, Hopefully following is what you want,
Thanks,
For every form, you just need to insert
Dim x As New Class1
x.TempClass(Me)
For example code
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim x As New Class1
x.TempClass(Me)
End Sub
End Class
and then you should create a new class for all CheckBoxs action, like below
Public Class Class1
Public Function TempClass(ByRef form As Control)
Dim allTxt As New List(Of Control)
For Each txt As CheckBox In FindControlRecursive(allTxt, form, GetType(CheckBox))
txt.Enabled = False
txt.Checked = False
Next
Return form
End Function
Public Shared Function FindControlRecursive(ByVal list As List(Of Control), ByVal parent As Control, ByVal ctrlType As System.Type) As List(Of Control)
If parent Is Nothing Then Return list
If parent.GetType Is ctrlType Then
list.Add(parent)
End If
For Each child As Control In parent.Controls
FindControlRecursive(list, child, ctrlType)
Next
Return list
End Function
End Class
Finally I got a solution:
For Each cc As Control In Me.Controls
If TypeOf cc Is CheckBox Then
DirectCast(cc, CheckBox).Checked = False
End If
Next
For Each cc As Control In Form1.Controls
If TypeOf cc Is CheckBox Then
DirectCast(cc, CheckBox).Checked = False
End If
Next

Creating a Combobox from a Class - In VB.net

im new to vb.net, and my query is:
file: read.vb
Friend Function Nav()
Dim NavBox As New ComboBox()
NavBox.Size = New System.Drawing.Size(44, 21)
NavBox.Location = New System.Drawing.Point(135, 305)
NavBox.DropDownStyle = ComboBoxStyle.DropDownList
NavBox.Items.Add("1")
NavBox.Items.Add("2")
NavBox.Items.Add("3")
NavBox.Items.Add("4")
NavBox.Items.Add("5")
NavBox.Items.Add("6")
NavBox.Items.Add("7")
NavBox.Items.Add("8")
NavBox.Items.Add("9")
NavBox.Items.Add("10")
NavBox.Items.Add("11")
AddHandler (NavBox.SelectionChangeCommitted), AddressOf MSGB
NavBox.Show()
Return NavBox
End Function
Public Sub MSGB(ByVal sender As Object, ByVal e As System.EventArgs)
Dim cb As ComboBox = DirectCast(sender, ComboBox)
MsgBox(cb.SelectedItem)
End Sub
And im calling this function or displaying this combobox in mainFrom.vb
file: mainFrom.vb
Dim l As New read
Me.Controls.Add(CType(l.Nav(), Control))
Now what i need is, a access to its control so i can parss value from mainFrom.vb to read.vb to manipulation the SelectionChangeCommitted activity.
I hope my question is clear....
Since you control is a simple ComboBox, I don't see the point of having common code to create this control. You can have a common function to populate it's contents though.
If you want to add functionality to the ComboBox, just create your own combo box class, let's say ExtendedComboBox, which inherits from ComboBox, and use it in your forms.
If you don't want to change your existing code, you can assign your ComboBox returned from Nav to a variable, and then hook into events from this ComboBox:
Public Class MainForm
'Declare NavBox as a form member
Private NavBox As ComboBox
Public Sub MainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Create NavBox
Dim read As New read
NavBox = read.Nav()
'Hook NavBox event so MainForm knows when selection is changed
AddHandler NavBox.SelectionChangeCommitted, AddressOf NavBox_SelectionChangedCommited
'Add NavBox to MainForm
Me.Controls.Add(NavBox)
End Sub
Public Sub NavBox_SelectionChangedCommited(ByVal sender As Object, ByVal e As System.EventArgs)
Dim cb As ComboBox = DirectCast(sender, ComboBox)
'Do something when selection changes.
End Sub
End Class
You should also remove the useless AddHandler line inside the Nav function.