Clearing many textbox controls in vb.net at once - vb.net

I am using the following code to clear the
txtint1.Clear()
txtext1.Clear()
txttot1.Clear()
txtint2.Clear()
txtext2.Clear()
txttot2.Clear()
txtint3.Clear()
txtext3.Clear()
txttot3.Clear()
txtint4.Clear()
txtext4.Clear()
txttot4.Clear()
txtint5.Clear()
txtext5.Clear()
txttot5.Clear()
txtint6.Clear()
txtext6.Clear()
txttot7.Clear()
txtint8.Clear()
txtext8.Clear()
txttot8.Clear()
Is there any possibility to clear all the textbox controls at once or with few lines of code?

You can iterate over all controls on the form which are contained in root.Controls and see if it is of type a textbox TypeOf ctrl Is TextBox, then you can clear the text in that control CType(ctrl, TextBox).Text = String.Empty
Well!! You need to use recursion to loop through all controls
Adding the code:
Public Sub ClearTextBox(parent As Control)
For Each child As Control In parent.Controls
ClearTextBox(child)
Next
If TryCast(parent, TextBox) IsNot Nothing Then
TryCast(parent, TextBox).Text = [String].Empty
End If
End Sub

You could put them in an array then loop through the array:
For Each txt In {txtint1, txtext1, txttot1, txtint2, txtext2, txttot2, txtint3, txtext3, txttot3, txtint4, txtext4, txttot4, txtint5, txtext5, txttot5, txtint6, txtext6, txttot7, txtint8, txtext8, txttot8}
txt.Clear()
Next

I tried one of the examples here but this seems to work for me:
Dim a As Control
For Each a In Me.Controls
If TypeOf a Is TextBox Then
a.Text = Nothing
End If
Next

Try this
For Each txt As Control In Me.Controls.OfType(Of TextBox)()
txt.Text = ""
Next

try this one
Dim a As Control
For Each a In Me.Controls
If TypeOf a Is TextBox Then
a.Text = ""
End If
Next
or
Dim a As Control
For Each a In Me.Controls
If TypeOf a Is TextBox Then
a.clear()
End If
Next
if .Clear() is a member of textbox property then use it. i guess .clear() is not a member of textbox properties.

This is my code that I personally use it in my projects ^_^
ClearAll TextBoxes :
For Each TxtBox In Me.Controls.OfType(Of TextBox)
TxtBox.Clear()
Next TxtBox

I had to cast the Control as a TextBox to make this work. Something about the control object not being accessible. There may be a more direct way but I was unable to find one.
I got the idea from https://stackoverflow.com/a/16264904/11242863
Private Sub clearAllTextBoxes()
Dim formControl As Control
Dim txtBox As TextBox
For Each formControl In Me.Controls
If TypeOf formControl Is TextBox Then
txtBox = TryCast(formControl, TextBox)
txtBox.Clear()
End If
Next
End Sub
I hope this helps someone,
Tim R

This Will Reset All controls on Form To Default Value
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Controls.Clear()
InitializeComponent()
Form1_Load(Me, Nothing)
End Sub

This code is tested and the best code I have used:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Controls.Clear()
InitializeComponent()
Form1_Load(Me, Nothing)
End Sub

Related

Select All Controls on Form

I am trying to implement a clear all button on a form that clears the textbox contents and unchecks all checkboxes. The issue is that the controls that need to be accessed are contained within Groupboxes and thus cannot be acessed via Me.Controls collection. I saw a similar post here: VB Uncheck all checked checkboxes in forms, but the answer seems to be more complex than I would expect it should be. Is there any easier way other than in that post.
I tried this code, which logically to me should work but it does not:
'Get textboes and clears them
For Each ctrGroupBoxes As Control In Me.Controls.OfType(Of GroupBox)
For Each ctrControls As Control In ctrGroupBoxes.Controls.OfType(Of TextBox)
ctrControls.Text = ""
Next
Next
'Get checkboxes and unchecks them
For Each ctrGroupBoxes As Control In Me.Controls.OfType(Of GroupBox)
For Each ctrControls As Control In ctrGroupBoxes.Controls.OfType(Of CheckBox)
DirectCast(ctrControls, CheckBox).Checked = False
Next
Next
I know the inner for loops work as I used it to clear each GroupBox individually for a different button on the form.
Any assistance would be appreciated.
Here's one option that should work regardless of the UI hierarchy:
Dim cntrl = GetNextControl(Me, True)
Do Until cntrl Is Nothing
Dim tb = TryCast(cntrl, TextBox)
If tb IsNot Nothing Then
tb.Clear()
Else
Dim cb = TryCast(cntrl, CheckBox)
If cb IsNot Nothing Then
cb.Checked = False
End If
End If
cntrl = GetNextControl(cntrl, True)
Loop
That will follow the Tab order on the form
A recursive function really isn't that difficult:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ClearForm(Me)
End Sub
Private Sub ClearForm(ByVal C As Control)
For Each ctl As Control In C.Controls
If TypeOf ctl Is TextBox Then
ctl.Text = ""
ElseIf TypeOf ctl Is CheckBox Then
DirectCast(ctl, CheckBox).Checked = False
ElseIf ctl.HasChildren Then
ClearForm(ctl)
End If
Next
End Sub
End Class

Disable textboxes with the corresponding checkboxes in VB.net

Public Class Form1
Dim controlNames() As String = {"Tea", "Cola", "Coffee", "Orange", "Water", "VanillaCone", "VanillaShake", "StrawberryShake", "ChocolateMilkshake", "Fries", "Salad", "Hamburger", "OnionRings", "ChickenSalad", "FishSandwich", "CheeseSandwich", "ChickenSandwich"}
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
For Each ctrl As Control In Me.Panel2.Controls
If TypeOf ctrl Is TextBox Then
ctrl.Enabled = False
End If
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs)
For i = 0 To 16
For Each ctrl As Control In Me.Panel2.Controls
If TypeOf ctrl Is CheckBox Then
If ctrl.Name = "chk" & controlNames(i) Then
If DirectCast(ctrl, CheckBox).CheckState = CheckState.Checked Then
If TypeOf ctrl Is TextBox Then
If ctrl.Name = "txt" & controlNames(i) Then
ctrl.Enabled = True
End If
End If
End If
End If
End If
Next
Next
End Sub
I have a VB.NET assignment and I am attempting to enable textboxes based on whether or not the checkbox with the same name was checked.
This is my code so far and it obviously doesn't work. What I want to do essentially:
All textboxes start as disabled. Then, textboxes only get enabled if the corresponding checkboxes are checked. For example, if chkTea is checked, then it enables txtTea.
I am aware I can copy paste something like "if chkTea = checked then txt.tea = enabled". I do not want to do this as this seems like a poor way to go about this. I want to know if I can do something like my barely readable code shows.
If you're renaming all your controls to something different to the default name with a number, this code should work just fine.
You dont need a timer, it just fires when any of the CheckBoxes have their state changed.
In the example code, I've created a CheckedChanged handler and set it to handle some of the CheckBoxes (You'll want to add all those you want to handle). If you click on any of these CheckBoxes, the handler will fire. The handler then passes which checkbox has been changed to the SyncTextBoxWithCheckBoxState method. This then finds the matching textbox using the FindMatchingCheckBox method and sets the .Enabled state of the Text box to the same as the .Checked state of the CheckBox
Private Sub chkTea_CheckedChanged(sender As Object, e As EventArgs) Handles chkTea.CheckedChanged, chkCoffee.CheckedChanged, chkCola.CheckedChanged, chkOrange.CheckedChanged, chkTea.CheckedChanged, chkVanillaCone.CheckedChanged, chkVanillaCone.CheckedChanged, chkWater.CheckedChanged
SyncTextBoxWithCheckBoxState(CType(sender, CheckBox))
End Sub
Private Sub SyncTextBoxWithCheckBoxState(chkBox As CheckBox)
Dim txtBox As TextBox = FindMatchingTextBox(chkBox)
txtBox.Enabled = chkBox.Checked
End Sub
Private Function FindMatchingTextBox(chkbox As CheckBox) As TextBox
For Each ctrl As Control In Panel2.Controls
If ctrl.GetType Is GetType(TextBox) And ctrl.Name.Contains(chkbox.Name.Substring(3)) Then
Return CType(ctrl, TextBox)
End If
Next
Return Nothing
End Function
EDIT
To have the code target more than one panel, add all the checkboxes you want to detect to the event handler like before, and in the FindMatchingTextBox method, just add another loop around the existing one to loop through each panel. Like so ..
Private Function FindMatchingTextBox(chkbox As CheckBox) As TextBox
'This is the new loop which loops through the two panels. It's
'a bit quick and dirty, but it works
For Each pnl As Panel In New Panel() {Panel2, Panel3}
'In this line note that the reference to Panel2 now refers to pnl
For Each ctrl As Control In pnl.Controls
If ctrl.GetType Is GetType(TextBox) And ctrl.Name.Contains(chkbox.Name.Substring(3)) Then
Return CType(ctrl, TextBox)
End If
Next
'End point of the new loop
Next
Return Nothing
End Function
After you've looped through each checkbox, you are only concerned with that checkbox, so when you find the correct checkbox, you need to then RELOOP back through all the controls on the form checking if they are the corresponding textbox.
Something like the below should work, or at the very least start you off down the right path:
Dim controlNames() As String = {"Tea", "Cola", "Coffee", "Orange", "Water", "VanillaCone", "VanillaShake", "StrawberryShake", "ChocolateMilkshake", "Fries", "Salad", "Hamburger", "OnionRings", "ChickenSalad", "FishSandwich", "CheeseSandwich", "ChickenSandwich"}
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
For Each ctrl As Control In Me.Panel2.Controls
If TypeOf ctrl Is TextBox Then
ctrl.Enabled = False
End If
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs)
For i = 0 To 16
For Each ctrl As Control In Me.Panel2.Controls
If TypeOf ctrl Is CheckBox Then
If ctrl.Name = "chk" & controlNames(i) Then
If DirectCast(ctrl, CheckBox).CheckState = CheckState.Checked Then
For Each ctrl As Control In Me.Panel2.Controls
If TypeOf ctrl Is TextBox Then
If ctrl.Name = "txt" & controlNames(i) Then
ctrl.Enabled = True
End If
End If
Next
End If
End If
End If
Next
Next
End Sub

Loop over controls in another class

I have created one form with two datagridviews, two text boxes with some random text, and two combo boxes with some random text.
I have created two classes. DataGridViewForm and DataGridViewClass
I loop over the controls on the DataGridViewForm to clear the controls
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Pressing this button will clear all text and comboboxes
Dim button As New DataGridViewClass()
Dim a As Control = Nothing
For Each a In Me.Controls
button.Wissen = a
Next
End Sub
and it the DataGridViewClass
Property Wissen() As Control
Get
Return ControlName
End Get
Set(value As Control)
ControlName = value
If TypeOf ControlName Is TextBox Then
ControlName.Text = Nothing
ElseIf TypeOf ControlName Is ComboBox
ControlName.Text = String.Empty
End If
End Set
End Property
This works fine, but I would like to move the loop from the dgvFrom to the dgvClass. How would I do that? If I would move that loop I get the error "Controls is not a member of DataGridViewClass"
Okay, on the suggestion I tried this:
ControlName = value
Dim a As Control
For Each a In ControlName.Controls
If TypeOf a Is TextBox Then
a.Text = Nothing
ElseIf TypeOf a Is ComboBox
a.Text = String.Empty
End If
Next
And in DataGridViewForm I put
Dim button As New DataGridViewClass()
button.Wissen = Me
This works! Now I can use the same Clear button for other forms. Thanks!
The controls of DataGridViewForm are not static, you need to pass an instance of DataGridViewForm to an instance of DataGridViewClass and then DataGridViewClass will have access to all controls of DataGridViewForm, here is a basic example:
Public Class DataGridViewForm
Private DgvClassObj As DataGridViewClass
Sub New()
' pass this DataGridViewForm instance (Me) to an instance of DataGridViewClass
Init()
End Sub
Private Sub Init()
DgvClassObj = New DataGridViewClass(Me)
DgvClassObj.SomeMethodToLoopOverDataGridViewFormControls()
End Sub
End Class
Class DataGridViewClass
Private DgFormObj As DataGridViewForm
Sub New(ByRef dgform As DataGridViewForm)
Me.DgFormObj = dgform
End Sub
Public Sub SomeMethodToLoopOverDataGridViewFormControls()
For Each c As Control In DgFormObj.Controls
' now you can loop over the instance of your DataGridViewForm class
Next
End Sub
End Class

How to notice any change on a form

I have a form with many different radiobuttons, checkboxes and textboxes. Depending on their values I start my calculations. The results are shown on the same form and panel. If any of my controls (checkboxes, ...) changes, I want to immediatly update the results without a need to press any update-button.
I could define a statsChanged-sub for every single control on the form but there are so many. Isn't there a way/event of the form starting whenever a control is changed? It should be something like controlOnFormChanged. How can I get a sub that starts whenever a any control on the form changed?
Thank you in advance!
You could wire up the events that correspond to the desired change manually to a specific event handler:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Iterate through all controls and handle them according to their type
For Each c As Control In Me.Controls
If TypeOf (c) Is CheckBox Then
AddHandler CType(c, CheckBox).CheckedChanged, AddressOf SomethingChanged
ElseIf TypeOf (c) Is RadioButton Then
AddHandler CType(c, RadioButton).CheckedChanged, AddressOf SomethingChanged
ElseIf TypeOf (c) Is TextBox Then
AddHandler CType(c, TextBox).TextChanged, AddressOf SomethingChanged
ElseIf ......
......
End If
Next
End Sub
Private Sub SomethingChanged(sender As Object, e As EventArgs)
'Whatever it is you do
End Sub
End Class
Whenever one of the events on a control fires the sub SomethingChanged is called, allowing you to update your results.
Please be aware: If you have controls in subcontainers like Panels you need to modify this method and iteratively get all controls in all containers.
Here is, for example, a solution to this:
http://kon-phum.com/tutors/pascal/programming_cs_getcontrolsonform.html
Public Shared Function GetAllControls(ctrls As IList) As List(Of Control)
Dim RetCtrls As New List(Of Control)()
For Each ctl As Control In ctrls
RetCtrls.Add(ctl)
Dim SubCtrls As List(Of Control) = GetAllControls(ctl.Controls)
RetCtrls.AddRange(SubCtrls)
Next
Return RetCtrls
End Function

Why are controls missing from Me.Controls()

Hey guys. I must be missing something. I am trying to cycle throught the lables on my form but it would appear that I am missing quite a few labels... I have a total of 69 lables on my form and I only get 5 hits on the msgbox. All controls were placed on design time on the form and not on panels or tabs. Also upon inspecting the me.controls. the count is incorrect as it is missing exactly 64 controls. (The missing lables).
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is Label Then
MsgBox(ctl.Name)
End If
Next ctl
Any ideas why they would not show up?
Brad Swindell
The Controls collection is a heirarchy. You are only getting top level controls. If you want to get all controls then you will need to recursively dig into each child controls Control collection.
All controls were placed on design
time on the form and not on panels or
tabs.
Remember that GroupBox is also a control, with it's own Controls property as well.
This function should give you what you want, but my VB.Net is very, very rusty so if it doesn't compile I apologize.
Private Sub PrintAllControlsRecursive(col As Control.ControlCollection, ctrlType As Type)
If col Is Nothing OrElse col.Count = 0 Then
Return
End If
For Each c As Control In col
If c.GetType() = ctrlType Then
MessageBox.Show(c.Name)
End If
If c.HasChildren Then
PrintAllControlsRecursive(c.Controls, ctrlType)
End If
Next
End Sub
Sub PrintAllControls(ByVal ParentCtl As Control)
Dim ctl As Control
MsgBox(ParentCtl.Name + " start", MsgBoxStyle.Exclamation)
For Each ctl In ParentCtl.Controls
MsgBox(ctl.Name)
If ctl.HasChildren = True Then
PrintAllControls(ctl)
End If
Next
MsgBox(ParentCtl.Name + " End", MsgBoxStyle.Information)
End Sub
Flatten.
Just use LINQ and a recursive lambda with selectmany to flatten the hierarchy:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim act As Func(Of Control, IEnumerable(Of Control)) =
Function(ctl) ctl.Controls.Cast(Of Control)().SelectMany(
Function(ctl2) ctl2.Controls.Cast(Of Control)().
Union(act(ctl2))).Union(ctl.Controls.Cast(Of Control))
MsgBox(Join((From c In act(Me).Distinct Order By c.Name
Select c.Name & "--" & c.GetType.ToString).ToArray, vbCrLf))
End Sub
Not barnyard programming at all nor chance of repeated items or obscure bugs...
be sure that you're finding controls AFTER the form has been completelly charged, otherwise if you try to list controls during load process the me.controls.count will be zero.