Disable textboxes with the corresponding checkboxes in VB.net - 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

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

How do I code out with numeric keypads with multi textboxes?

I'm trying to code out a programme where the user sees a form and in that form, there are 2 text boxes and 10 buttons.
Username:
Password:
1 2 3
4 5 6
7 8 9
0
I've tried this code
Private Sub Btn1_Click(sender As Object, e As EventArgs) Handles Btn1.Click
If UsernameTextbox.Focused = True Then
UsernameTextbox.Text = UsernameTextbox.Text + "1"
End If
End Sub
I understand that clicking on Btn1 will steal the focus from the text box. So how can I write the programme?
One option would be to declare a variable of type Control and, in the Leave event handler for each control, assign the sender to that variable. You can then use that variable in the Click event handler of your Button to determine which control had focus and possibly reassign back to that control and then update it appropriately. You can do the lot with two event handlers, e.g.
Private previouslyActiveTextBox As TextBox
Private Sub TextBoxes_Leave(sender As Object, e As EventArgs) Handles TextBox2.Leave,
TextBox1.Leave
previouslyActiveTextBox = DirectCast(sender, TextBox)
End Sub
Private Sub Buttons_Click(sender As Object, e As EventArgs) Handles Button3.Click,
Button2.Click,
Button1.Click
previouslyActiveTextBox.Select()
previouslyActiveTextBox.SelectedText = CStr(DirectCast(sender, Button).Tag)
End Sub
That code handles multiple events with a single method in both cases. It also requires that you assign the number for each Button to the Tag property of that control. Note that it also sets the SelectedText, rather than appending to the Text property. That is more correct because it will add the new text where the caret is actually located and replace text if it is selected.
An even better option might be to use a custom button control that doesn't take focus. Here's one I prepared earlier:
http://www.vbforums.com/showthread.php?459890-Building-Blocks-for-an-On-screen-Keyboard
Items within a ToolStrip do not grab focus when clicked. While the standard ToolStrip usage is as a menu bar, there is nothing that prevents you from using it as a container for buttons laid out in a grid. In fact, the class ToolStrip.LayoutStyle Property allows you select a table style.
The following is a proof-of-concept custom ToolStrip that is prepopulated with the buttons to create a number pad like control. The control has sufficient function to work as intended, but is not locked down to prevent misuse by manipulating the Items collection and other properties.
Public Class NumPadToolstrip : Inherits ToolStrip
Private _ButtonSize As Size = New Size(50, 50)
Private _ButtonMargin As Padding = New Padding(5)
Private _ButtonBackColor As Color = Color.Ivory
Public Sub New()
MyBase.New
LayoutStyle = ToolStripLayoutStyle.Table
Dim settings As TableLayoutSettings = CType(LayoutSettings, TableLayoutSettings)
settings.ColumnCount = 3
settings.RowCount = 4
AddButtons(7, 9)
AddButtons(4, 6)
AddButtons(1, 3)
AddButtons(0, 0)
Dock = DockStyle.None
AutoSize = True
BackColor = Color.LightGray
End Sub
Public Property ButtonSize As Size
Get
Return _ButtonSize
End Get
Set(value As Size)
If value <> _ButtonSize Then
_ButtonSize = value
UpdateButtonSizes()
End If
End Set
End Property
Public Property ButtonMargin As Padding
Get
Return _ButtonMargin
End Get
Set(value As Padding)
If value <> _ButtonMargin Then
_ButtonMargin = value
UpdateMargins()
End If
End Set
End Property
Public Property ButtonBackColor As Color
Get
Return _ButtonBackColor
End Get
Set(value As Color)
If value <> _ButtonBackColor Then
_ButtonBackColor = value
UpdateButtonBackColor()
End If
End Set
End Property
Private Sub AddButtons(start As Int32, [end] As Int32)
For num As Int32 = start To [end]
Dim b As New ToolStripButton With {.Text = num.ToString(),
.Size = ButtonSize,
.Margin = ButtonMargin,
.BackColor = ButtonBackColor,
.AutoSize = False}
AddHandler b.Paint, Sub(sender As Object, e As PaintEventArgs)
With e.Graphics
Dim r As Rectangle = e.ClipRectangle
r.Inflate(-1, -1)
r.Location = Point.Empty
.DrawRectangle(Pens.Black, r)
End With
End Sub
Items.Add(b)
Next
End Sub
Private Sub UpdateButtonSizes()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Size = _ButtonSize
Next
ResumeLayout()
End Sub
Private Sub UpdateMargins()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.Margin = _ButtonMargin
Next
ResumeLayout()
End Sub
Private Sub UpdateButtonBackColor()
SuspendLayout()
For Each btn As ToolStripButton In Items.OfType(Of ToolStripButton)
btn.BackColor = _ButtonBackColor
Next
ResumeLayout()
End Sub
End Class
Add the above class to your project and perform a build operation. The NumPadToolstrip control should then be available in the ToolBox. Add the control to the form and then add a handler for its ItemClicked event to pass the proper text to the TextBox.
Private Sub NumPadToolstrip1_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles NumPadToolstrip1.ItemClicked
Dim tb As TextBoxBase = TryCast(ActiveControl, TextBoxBase)
If tb IsNot Nothing Then tb.SelectedText = e.ClickedItem.Text
End Sub

show tooltip on disabled button inside multiple controls

I would like to display the tooltip on a disabled button, I've tried the code below but it looks not to be working.
I think that's because the button is inside a group box and the group box inside a panel, the panel is inside the form.
the code reported would work only if the button is directly on the form..
Private toolTipShown As Boolean = False
Private Sub TimeWorks_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
Dim parent = TryCast(sender, Control)
If parent Is Nothing Then
Return
End If
Dim ctrl = parent.GetChildAtPoint(e.Location)
If ctrl IsNot Nothing Then
If ctrl.Visible AndAlso toolTip1.Tag Is Nothing Then
If Not toolTipShown Then
Dim tipstring = toolTip1.GetToolTip(ctrl)
toolTip1.Show(tipstring.Trim(), ctrl, ctrl.Width / 2, ctrl.Height / 2)
toolTip1.Tag = ctrl
toolTipShown = True
End If
End If
Else
ctrl = TryCast(toolTip1.Tag, Control)
If ctrl IsNot Nothing Then
toolTip1.Hide(ctrl)
toolTip1.Tag = Nothing
toolTipShown = False
End If
End If
End Sub
Any suggestions to make the code working?

Clearing many textbox controls in vb.net at once

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

TextBox Enter Key - Sub Panels within a main Panel

I am having a problem with this scenario (See Title). I have 6 Sub Panels within one big Panel. I have made a TextBox class that inherits from the main Textbox. I am trying to use the KeyPressed Event Handler for handling the Enter key. When a User presses the Enter Key, it moves from one TextBox inside a sub panel into the next sub panel. So far, I have gotten the Enter Key Event handler to work for the panel where the focus is without jumping to the next panel.
Below is subroutine that I am using to control the movements.
The problem is that I am unable to jump from one sub panel to another. Any help would be appreciated!
Protected Shared Sub NextControl(ByVal tControl As Control, ByVal Direction As Boolean)
Dim pControl As Control = tControl.TopLevelControl
tControl = pControl.GetNextControl(tControl, Direction)
If Direction = False Then
Dim tParent As Control
While TypeOf tControl Is UserControl
tParent = tControl.Parent
tControl = pControl.GetNextControl(tControl, Direction)
If tControl.Parent Is tParent Then
Exit While
End If
End While
End If
If tBox_P00.ControlNesting > 0 Then
'Dim i As Integer
pControl = tControl.Parent
For i As Integer = 0 To tBox_P00.ControlNesting - 2
pControl = pControl.Parent
Next
End If
If Not tControl Is Nothing Then
Do Until (tControl.TabStop = True) AndAlso (tControl.Enabled = True) AndAlso (tControl.Visible = True) AndAlso (TypeOf tControl Is Tbx00)
tControl = pControl.GetNextControl(tControl, Direction)
'Last in the Panel
If tControl Is Nothing Then
tBox_P00.Select(0, tBox_P00.TextLength)
Beep()
Exit Sub
End If
Loop
tControl.Focus()
Else
tBox_P00.Select(0, tBox_P00.TextLength)
Beep()
End If
Exit Sub
End Sub
It sounds as though you are complicating things. As HansPassant mentioned you can use GetNextControl to do the work for you:
This code will move the focus to the next textbox on the form (based on tab index order) when enter is pressed:
Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
If e.KeyCode = Keys.Enter Then
Dim ctl As Control = CType(sender, Control)
Do
ctl = Me.GetNextControl(ctl, True)
Loop Until TypeOf ctl Is TextBox
ctl.Focus()
End If
End Sub
You could then expand this to handle all textbox KeyDown events.