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

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

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.

How to AddHandler to Multiple Items and Properly Reference Said Handler

I'm writing a program wherein I need to create GotFocus and LostFocus event handlers for every text box.
What I have now creates an error whenever any text box in the form is clicked on:
Private Sub lblTotalWeight_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each cnt In Me.Controls.OfType(Of TextBox)
AddHandler cnt.GotFocus, AddressOf txtBox_GotFocus
Next
End Sub
Private Sub txtBox_GotFocus(sender As System.Object, e As System.EventArgs)
Dim textBox As TextBox = Me.Controls.OfType(Of TextBox)
textBox.ForeColor = Color.White
textBox.BackColor = Color.LightGray
End Sub
I'm getting an error with the Dim textBox as TextBox = Me.Controls.OfType(Of TextBox), and I have no idea why or how to fix it.
There will be another Private Sub for a lost focus event that will be nearly identical, if it helps.
Any help would be appreciated
Me.Controls.OfType(Of TextBox) returns a list of controls that are textboxes. It works great in your AddHandler call, but in your event handler you need to use sender as Textbox instead.
Dim textBox As TextBox = DirectCast(sender, Textbox)
This code:
Me.Controls.OfType(Of TextBox)
returns an IEnumerable(Of TextBox). It's not a single Textbox so you can't assign it to a TextBox variable. You need to access the TextBox that raised the event:
Dim textBox As TextBox = DirectCast(sender, TextBox)
In an event handler, the sender parameter is always the object that raised the event.
Me.Controls.OfType(Of TextBox) with replace CType(sender, TextBox) for event txtBox_GotFocus

How to Set BackColor of Inactive Control

I have a form that contains several Textboxes and Comboboxes. I have set active control's back color property to skyblue. I want to set the back color of all textboxes and comboboxes to white while they are not active.
There's a Right Way and a wrong way to do this. You are asking for the wrong way. The right way is to derive your own class from TextBox and override the OnEnter and OnLeave methods. Repeat for ComboBox.
But you ask for the wrong way and you are probably trying to add this feature too late so we'll have to slug it out by finding the controls back at runtime. Add a constructor to your form class and make it look like:
Public Sub New()
InitializeComponent()
FindControls(Me.Controls)
End Sub
Private Sub FindControls(ctls As Control.ControlCollection)
For Each ctl As Control In ctls
Dim match As Boolean
If TypeOf ctl Is TextBoxBase Then match = True
If TypeOf ctl Is ComboBox Then
Dim combo = DirectCast(ctl, ComboBox)
If combo.DropDownStyle <> ComboBoxStyle.DropDownList Then match = True
End If
If match Then
AddHandler ctl.Enter, AddressOf ControlEnter
AddHandler ctl.Leave, AddressOf ControlLeave
End If
FindControls(ctl.Controls)
Next
End Sub
Private controlColor As Color
Private Sub ControlEnter(sender As Object, e As EventArgs)
Dim ctl = DirectCast(sender, Control)
controlColor = ctl.BackColor
ctl.BackColor = Color.AliceBlue
End Sub
Private Sub ControlLeave(sender As Object, e As EventArgs)
Dim ctl = DirectCast(sender, Control)
ctl.BackColor = controlColor
End Sub

Trapping WM_SETFOCUS in WindProc VB.NET

I have a user control that inherits from a base user control class. On the user control that inherits this, I place a series of textboxes. At runtime, I need to know when each control gets focus and loses focus. To do this, I overrode WndProc in the base class, and am attempting to capture the messages there. The problem I'm having is that I never receive WM_SETFOCUS or WM_KILLFOCUS within the message loop.
This is the WndProc:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_SETFOCUS
Debug.WriteLine(m.ToString())
Case WM_KILLFOCUS
Debug.WriteLine(m.ToString())
Case Else
Debug.Print("OTHER: " + m.ToString())
End Select
MyBase.WndProc(m)
End Sub
I get a whole bunch of message for getting text and some other stuff, so I know that I'm getting there. It just never stops on WM_SETFOCUS or WM_KILLFOCUS.
What am I not doing correctly.
Quick example of wiring up all TextBoxes in the UserControl:
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles Me.Load
WireTBs(Me)
End Sub
Private Sub WireTBs(ByVal cont As Control)
For Each ctl As Control In cont.Controls
If TypeOf ctl Is TextBox Then
Dim TB As TextBox = DirectCast(ctl, TextBox)
AddHandler TB.GotFocus, AddressOf TB_GotFocus
AddHandler TB.LostFocus, AddressOf TB_LostFocus
ElseIf ctl.HasChildren Then
WireTBs(ctl)
End If
Next
End Sub
Private Sub TB_GotFocus(sender As Object, e As EventArgs)
Dim TB As TextBox = DirectCast(sender, TextBox)
' ... do something with "TB" ...
Debug.Print("GotFocus: " & TB.Name)
End Sub
Private Sub TB_LostFocus(sender As Object, e As EventArgs)
Dim TB As TextBox = DirectCast(sender, TextBox)
' ... do something with "TB" ...
Debug.Print("LostFocus: " & TB.Name)
End Sub
End Class

Detecting the ID of checkbox that was checked

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