I am herewith develop an application but I have created a class which calls button events(i.e. enable or visible)
Public Class ClassfrmLoad
Dim btnAdd As New Button
Dim btnEdit As New Button
Private Sub FormLoad()
Me.btnAdd.Visible = True
Me.btnAdd.Enabled = True
Me.btnEdit.Visible = True
Me.btnEdit.Enabled = False
End Sub
End Class
I am actually created the button events class(classfrmLoad) for the way which buttons should be enabled and visible when each & every form loading.
There are 6 buttons in the forms (frm1, frm2 etc.,) like btnAdd, btnEdit, btnCancel etc., i don't want to display the buttons(visible/enable) while loading the form.
Here is the question:
How can i call this class(classfrmLoad) events to alter (enable/visible) the buttons positioned in the forms(frm1, frm2, etc.,) and how to get the buttons events in those forms?
Dear Sergio,
Thanks for your immediate response. I am missing something and it is not as expected, here is my complete code for the form including yours.
This is the code you suggested for the classfrmLoad:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd"
btn.Visible = True
btn.Enabled = True
Case "btnsave"
btn.Visible = False
btn.Enabled = False
Case "btnedit"
btn.Visible = True
btn.Enabled = True
Case "btncancel"
btn.Visible = True
btn.Enabled = False
Case "btnclose"
btn.Visible = True
btn.Enabled = True
Case "btnupdate"
btn.Visible = False
btn.Enabled = False
Case "btnfind"
btn.Visible = False
btn.Enabled = False
'and so on
End Select
Next
End Sub
End Class
This is the code for the formload event:
Private Sub frmCreate_Unit_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
'Display software and title of the page
Me.Text = msgCap & " | " & " CREATE UNIT"
Me.lblComp.Text = CompName
Me.stBar_User.Text = frmMain.stBar_User.Text
Me.stBar_UserID.Text = frmMain.stBar_UserID.Text
Me.stBar_G_ID.Text = frmMain.stBar_G_ID.Text
Me.stBar_G_No.Text = frmMain.stBar_G_No.Text
Me.cboUnit.Visible = False
Me.txtUnit_Long.Visible = True
Me.btnfind.Visible = False
Me.txtUnit_ID.Enabled = False
Me.btnadd.Focus()
End Sub
Please help me to sort out this one. Thanks...
Every form in WinForms is a class instance, inherited from Form class.
Because of this, you cannot make static references to it's members from another class, given any Form instance.
Generic class won't cut it either because you're after specific class members.
I would take advantage of the Controls collection and would check it's name and type. Once caught, we can cast the control to button and set it's visibility and access.
For this, you should make small adjustments to your code:
Public Class ClassfrmLoad
Public Shared Sub FormLoad(ByRef Target As Form)
For Each ctl As Control In Target.Controls
If Not TypeOf ctl Is Button Then Continue For
Dim btn As Button = DirectCast(ctl, Button)
Select Case btn.Name.ToLower()
Case "btnadd", "btnedit"
btn.Visible = True
btn.Enabled = True
'and so on
End Select
Next
End Sub
End Class
Changed the FormLoad visibility and access. It should be shared so we don't need to create unnecessary instances of this class
Added a parameter, passe by reference that referrs the target form. This will assure that you can use it on any class that inherits Form class
Iterated the Controls collection and find a candidate based on it's type and name
When found, we cast it to Button and access it's properties normally.
It's just an example, based on your code.
You should now call it on every Form's formload handler, like so:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ClassfrmLoad.FormLoad(Me)
End Sub
Finally I got the solution. It is very simple and any way thanks to sergio.
Here is the complete code.
Public Class ClassfrmLoad
Public Shared Sub formLoad(ByVal btnAdd As Button, ByVal btnEdit As Button, ByVal btnSave As Button, ByVal btnCancel As Button, ByVal btnClose As Button, ByVal btnUpdate As Button, ByVal btnFind As Button)
btnAdd.Visible = True
btnAdd.Enabled = True
btnSave.Visible = False
btnSave.Enabled = False
btnCancel.Visible = True
btnCancel.Enabled = False
btnClose.Visible = True
btnClose.Enabled = True
btnEdit.Visible = True
btnEdit.Enabled = True
btnUpdate.Visible = False
btnUpdate.Enabled = False
btnFind.Visible = False
btnFind.Enabled = False
End Sub
End Class
And calling proceedure in a form like this:
Dim x As New ClassfrmLoad
ClassfrmLoad.formLoad(Me.btnAdd, Me.btnEdit, Me.btnSave, Me.btnCancel, Me.btnClose, Me.btnUpdate, Me.btnFind)
Related
I'm calling a form from my main function, this form has a button on it; this form is defined inside its own class. My goal is that every time I click that button, the program will perform a task defined in the "click" event, but it will also perform a task in the main function at the moment of clicking that button.
I tried switching between oForm.Show(), but the main function runs the code before even starting the form. I also used oForm.Show(vbModeless), but this causes the opposite: the code in the main function runs after the form was closed.
This is my code:
Imports System.Windows.Forms
Public Sub Main()
Dim oForm As New WinForm()
oForm.Show(vbModeless)
' I want to show this when I click the button
MsgBox("TASK 2")
End Sub
Public Class WinForm
Inherits System.Windows.Forms.Form
Public Sub New()
oForm = Me
With oForm
.FormBorderStyle = FormBorderStyle.FixedToolWindow
.StartPosition = FormStartPosition.CenterScreen
.Width = 300
.Height = 400
.Text = "MYFORM"
.ShowInTaskbar = False
End With
Dim oButton1 As New Button()
With oButton1
.Text = "CLICK ME!"
.Top = oForm.Bottom - 80
.Left = (oForm.Width/2) - oButton1.Width
.Enabled = True
.AutoSize = True
End With
Me.Controls.Add(oButton1)
AddHandler oButton1.Click, AddressOf oButton1_Click
End Sub
Public Sub oButton1_Click(ByVal oSender As System.Object, ByVal oEventArgs As System.EventArgs)
MsgBox("TASK 1")
End Sub
End Class
How can I achieve this?
Thanks in advance
So I currently have a form where I have 4 teams, each with 4 teammates. This cannot change.
my form GUI
Initially when the program starts, it automatically selects the "current value" radio button which displays labels with blank data, you can then select "edit values" which can be saved by pressing the big green apply button. This stores the data under a 2d array named stTeamName, which the labels reference whenever you select "current value" again.
There are 4 radio buttons which allow you to switch between the teams.
My problem is, when I change the radio buttons, any data put into the text labels that has not been saved will be deleted.
I solved this problem by adding a message box which will stop the data in the labels from changing unless the user gives confirmation to do so.
However, my only problem is that after I cancel this, the radio button stays at the current selection which does not help.
I solved this issue by using rbTeamName1.Checked = True (rbTeamname 1 to 4 being the radio buttons named team 1-4) to switch back to the previous state.
This of course only goes back to rbTeamname1 no matter what, so I employed an 1d array and select case to help solve this issue.
"""
Dim RadioCounter(1) As Integer
the code below simply gives the default Radio button value on load.`
Sub DeclareRadio(RadioButton)
RadioButton(1) = 1
End Sub
"""
Whenever a radio button is successfully selected, RadioCounter(1) is set to the number 1-4 respectively. Whenever a new radio button is selected, the value of RadioCounter(1) is moved to RadioCounter(0) and the current radio button's value is to RadioCounter(1).
If the user selects no, RadioCounter(0)'s value is referenced and a select case selects the radio button.
(Please note, RadioTeam() is used as a counter to store Team name and Teammate name string variables correctly within the 2d array: stTeamName. I will most likely merge this with RadioCounter as soon as I get this problem fixed)
"""
Private Sub rbTeamName1_CheckedChanged(sender As Object, e As EventArgs) Handles rbTeamName1.CheckedChanged
'note txtTeamName starts at 0, however RadioTeam starts at 1, RadioTeam = 0 has no team designated to it.
'this function is for swapping teams via radio button, each time, a confirmation is given to make sure the user saves the current team, or risk deletion of the inputted data.
RadioCounter(1) = RadioCounter(0)
stTeamname(0, RadioTeam) = txtTeamName.Text
stTeamname(1, RadioTeam) = txtMate1.Text
stTeamname(2, RadioTeam) = txtMate2.Text
stTeamname(3, RadioTeam) = txtMate3.Text
stTeamname(4, RadioTeam) = txtMate4.Text
Dim Dialog As DialogResult
Dialog = MessageBox.Show("Are you sure you want to change team? Any unsaved changes will be lost. If this box shows on starting the program, just press no", "Change team?", MessageBoxButtons.YesNo)
If Dialog = DialogResult.No Then
'need to run function to check previous result of radio button'
Select Case RadioCounter(0)
Case 1
rbTeamName1.Checked = True
Case 2
rbTeamName2.Checked = True
Case 3
rbTeamName3.Checked = True
Case 4
rbTeamName4.Checked = True
End Select
ElseIf Dialog = DialogResult.Yes Then
RadioCounter(1) = 1 'this equals the respective number for each radio button'
RadioTeam = 1
txtTeamName.Text = stTeamname(0, RadioTeam)
txtMate1.Text = stTeamname(1, RadioTeam)
txtMate2.Text = stTeamname(2, RadioTeam)
txtMate3.Text = stTeamname(3, RadioTeam)
txtMate4.Text = stTeamname(4, RadioTeam)
lblTeamName.Text = stTeamname(0, RadioTeam)
lblMate1.Text = stTeamname(1, RadioTeam)
lblMate2.Text = stTeamname(2, RadioTeam)
lblMate3.Text = stTeamname(3, RadioTeam)
lblMate4.Text = stTeamname(4, RadioTeam)
End If
End Sub
"""
....Or it should do that. But it doesnt. Im not sure why, but when I force it to check a specific radio button, by removing the select case and only running rbTeamName4.Checked = True it will work perfectly fine, theres something about the select case that simply doesnt run the code.
Also, despite stTeamname(0, RadioTeam) = txtTeamName.Text etc. being given before the messagebox shows, if I do not press the apply button to save, press another team button, then press no, it will still not save those parameters, which I find extremely weird.
What is the ideal solution to this?
To clarify:
If a user writes team names and teammates and does not press the apply button to save and then changes team by selecting another radio button, a text box should appear asking whether they want to switch team and lose the data (Yes) or stay on the previous radio button to edit and apply the data (No).
Upon pressing no, the program automatically switches the current radio button to the previous selection to make it seem as if no radio button was selected in the first place.
And im not sure if I have to make it obvious but im new to both stackoverflow and VB.net in general. Thank you in advance.
Essentially what you are asking for is dirty form checking. The basic principle is that you need to compare the value to what it was previously.
So for example:
When the TextBox values change, set a form level boolean variable to true
When you go to switch teams or current/edit you would check if that form level boolean variable is true
If the variable is true then you would display the prompt, otherwise just do the action
After the action, reset the global level boolean variable
There are some caveats, for example, when you toggle between current/edit the check changed will fire twice: once for the current radio button and once for the edit. But you just need to work around those edge cases.
Here is a largely untested example for you to go off of:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class Form1
Private _team1 As Team
Private _team2 As Team
Private _team3 As Team
Private _team4 As Team
Private _isFormDirty As Boolean = False
Private _selectedTeamRadioButton = RadioButtonTeam1
Private Sub RadioButtonCurrent_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButtonCurrent.CheckedChanged
If (RadioButtonCurrent.Checked AndAlso _isFormDirty AndAlso MessageBox.Show("By doing this, you will lose all unsaved changes. Are you sure?", "Dirty Form", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
RadioButtonEdit.Checked = True
Return
End If
If (Not RadioButtonCurrent.Checked) Then
Return
End If
TextBoxTeamName.Enabled = False
TextBoxTeammate1.Enabled = False
TextBoxTeammate2.Enabled = False
TextBoxTeammate3.Enabled = False
TextBoxTeammate4.Enabled = False
ResetTeam()
End Sub
Private Sub RadioButtonEdit_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButtonEdit.CheckedChanged
TextBoxTeamName.Enabled = True
TextBoxTeammate1.Enabled = True
TextBoxTeammate2.Enabled = True
TextBoxTeammate3.Enabled = True
TextBoxTeammate4.Enabled = True
End Sub
Private Sub RadioButtonTeamChanged(sender As Object, e As EventArgs) Handles RadioButtonTeam1.CheckedChanged, RadioButtonTeam2.CheckedChanged, RadioButtonTeam3.CheckedChanged, RadioButtonTeam4.CheckedChanged
If (_selectedTeamRadioButton IsNot DirectCast(sender, RadioButton) AndAlso _isFormDirty AndAlso MessageBox.Show("By doing this, you will lose all unsaved changes. Are you sure?", "Dirty Form", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
_selectedTeamRadioButton.Checked = True
Return
End If
If (_selectedTeamRadioButton IsNot DirectCast(sender, RadioButton)) Then
Return
End If
_selectedTeamRadioButton = DirectCast(sender, RadioButton)
ResetTeam()
End Sub
Private Sub TextBoxTeamValueChanged(sender As Object, e As EventArgs) Handles TextBoxTeamName.TextChanged, TextBoxTeammate1.TextAlignChanged, TextBoxTeammate2.TextAlignChanged, TextBoxTeammate3.TextAlignChanged, TextBoxTeammate4.TextAlignChanged
_isFormDirty = True
End Sub
Private Sub ButtonApply_Click(sender As Object, e As EventArgs) Handles ButtonApply.Click
Select Case True
Case RadioButtonTeam1.Checked
_team1 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam2.Checked
_team2 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam3.Checked
_team3 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
Case RadioButtonTeam4.Checked
_team4 = New Team() With {
.Name = TextBoxTeamName.Text,
.Teammate1 = TextBoxTeammate1.Text,
.Teammate2 = TextBoxTeammate2.Text,
.Teammate3 = TextBoxTeammate3.Text,
.Teammate4 = TextBoxTeammate4.Text
}
End Select
_isFormDirty = False
End Sub
Private Sub ButtonDeleteTeam_Click(sender As Object, e As EventArgs) Handles ButtonDeleteTeam.Click
If (MessageBox.Show("Are you sure you want to delete this team?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No) Then
Return
End If
_isFormDirty = False
Select Case True
Case RadioButtonTeam1.Checked
_team1 = New Team()
Case RadioButtonTeam2.Checked
_team2 = New Team()
Case RadioButtonTeam3.Checked
_team3 = New Team()
Case RadioButtonTeam4.Checked
_team4 = New Team()
End Select
ResetTeam()
End Sub
Private Sub ResetTeam()
Dim selectedTeam As Team = Nothing
Select Case True
Case RadioButtonTeam1.Checked
selectedTeam = _team1
Case RadioButtonTeam2.Checked
selectedTeam = _team2
Case RadioButtonTeam3.Checked
selectedTeam = _team3
Case RadioButtonTeam4.Checked
selectedTeam = _team4
End Select
If (selectedTeam IsNot Nothing) Then
TextBoxTeamName.Text = selectedTeam.Name
TextBoxTeammate1.Text = selectedTeam.Teammate1
TextBoxTeammate2.Text = selectedTeam.Teammate2
TextBoxTeammate3.Text = selectedTeam.Teammate3
TextBoxTeammate4.Text = selectedTeam.Teammate4
Else
TextBoxTeamName.Clear()
TextBoxTeammate1.Clear()
TextBoxTeammate2.Clear()
TextBoxTeammate3.Clear()
TextBoxTeammate4.Clear()
End If
End Sub
End Class
Public Class Team
Implements INotifyPropertyChanged
Private _name As String
Public Property Name As String
Get
Return _name
End Get
Set(value As String)
If (_name <> value) Then
_name = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate1 As String
Public Property Teammate1 As String
Get
Return _teammate1
End Get
Set(value As String)
If (_teammate1 <> value) Then
_teammate1 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate2 As String
Public Property Teammate2 As String
Get
Return _teammate2
End Get
Set(value As String)
If (_teammate2 <> value) Then
_teammate2 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate3 As String
Public Property Teammate3 As String
Get
Return _teammate3
End Get
Set(value As String)
If (_teammate3 <> value) Then
_teammate3 = value
NotifyPropertyChanged()
End If
End Set
End Property
Private _teammate4 As String
Public Property Teammate4 As String
Get
Return _teammate4
End Get
Set(value As String)
If (_teammate4 <> value) Then
_teammate4 = value
NotifyPropertyChanged()
End If
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
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
My problem:
I have a checkbox I use to control if certain textboxes are enabled or not, and I need to do this around 30+ times. I've named my textboxes numerically/sequentially (TB_name_1, TB_name_2, etc) so if I know the Checkbox name I know which textboxes are affected.
My question:
Can I make a class for my checkboxes that says "if this box is checked/unchecked, then enable/disable these 3 textboxes" without the class also having to be told which textboxes (finds them itself)?
Here's the copy/paste code I'm currently using (not a class, obviously). I change the first 2 values and the rest of the code solves itself. (PS - I see you laughing)
Private Sub T1_cb_c_1_CheckedChanged(sender As Object, e As EventArgs) Handles T1_cb_c_1.CheckedChanged
'change here for current checkbox
Dim b As CheckBox = T1_cb_c_1
'change here for start value of first textbox (of 3), the next 2 will be in sequence
Dim a As Integer = 1
'How much of the below code can be moved to, and controlled from, a class?
Dim a1 As Integer = a + 1
Dim a2 As Integer = a + 2
Dim TB_PtNum As TextBox = Me.Controls.Find("T1_tb_c_" & a, True).FirstOrDefault
Dim TB_Qty As TextBox = Me.Controls.Find("T1_tb_c_" & a1, True).FirstOrDefault
Dim TB_Seq As TextBox = Me.Controls.Find("T1_tb_c_" & a2, True).FirstOrDefault
If b.Checked = True Then
TB_PtNum.Enabled = True
TB_Qty.Enabled = True
TB_Seq.Enabled = True
Else
TB_PtNum.Enabled = False
TB_Qty.Enabled = False
TB_Seq.Enabled = False
End If
End Sub
Here's a design time only class that will do this. You only have to the AssociatedCheckbox property in the designer:
Public Class TextBoxWithCheckboxProperty
Inherits TextBox
Private m_CheckBox As CheckBox
Public Property AssociatedCheckBox As CheckBox
Get
Return m_CheckBox
End Get
Set(value As CheckBox)
If Not m_CheckBox Is Nothing Then
RemoveHandler m_CheckBox.CheckedChanged, AddressOf OnCheckBoxChanged
End If
m_CheckBox = value
If Not value Is Nothing Then
AddHandler m_CheckBox.CheckedChanged, AddressOf OnCheckBoxChanged
End If
OnCheckBoxChanged(m_CheckBox, Nothing)
End Set
End Property
Private Sub OnCheckBoxChanged(ByVal sender As Object, ByVal e As System.EventArgs)
If Not sender Is Nothing Then
Me.Enabled = CType(sender, CheckBox).Checked
Else
Me.Enabled = False
End If
End Sub
End Class
Here's a sample Form1 that uses it:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.CheckBox1 = New System.Windows.Forms.CheckBox()
Me.TextBoxWithCheckboxProperty1 = New WindowsApp4.TextBoxWithCheckboxProperty()
Me.SuspendLayout()
'
'CheckBox1
'
Me.CheckBox1.AutoSize = True
Me.CheckBox1.Location = New System.Drawing.Point(293, 131)
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox1.Size = New System.Drawing.Size(81, 17)
Me.CheckBox1.TabIndex = 0
Me.CheckBox1.Text = "CheckBox1"
Me.CheckBox1.UseVisualStyleBackColor = True
'
'TextBoxWithCheckboxProperty1
'
Me.TextBoxWithCheckboxProperty1.AssociatedCheckBox = Me.CheckBox1
Me.TextBoxWithCheckboxProperty1.Location = New System.Drawing.Point(428, 131)
Me.TextBoxWithCheckboxProperty1.Name = "TextBoxWithCheckboxProperty1"
Me.TextBoxWithCheckboxProperty1.Size = New System.Drawing.Size(100, 20)
Me.TextBoxWithCheckboxProperty1.TabIndex = 1
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBoxWithCheckboxProperty1)
Me.Controls.Add(Me.CheckBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents CheckBox1 As CheckBox
Friend WithEvents TextBoxWithCheckboxProperty1 As TextBoxWithCheckboxProperty
End Class
I would use the property Tag for the related controls.
Suppose to set this property to the value "line1" for the first set of textboxes and on the checkbox that controls them.
Next row of controls (checkbox+textboxes) will have the property set to "line2" and so on until the last row. (You can do this through the Winforms Designer or through code)
At this point you could have a single event handler for all your checkboxes
Private Sub onCheckedChanged(sender As Object, e As EventArgs) _
Handles T1_cb_c_1.CheckedChanged, T2_cb_c_2.CheckedChanged, _
..... add other checkbox events here .......
' Get whatever checkbox has been clicked and extract its tag
Dim b As CheckBox = DirectCast(sender, CheckBox)
Dim tag = b.Tag.ToString()
' Find the textbox controls in this form with the same Tag
Dim ctrls = Me.Controls.OfType(Of TextBox).Where(Function(x) x.Tag.ToString() = tag)
' Enabled status matches the status of the Checked property
For Each c as TextBox in ctrls
c.Enabled = b.Checked
Next
End Sub
I have a pair of radio buttons on top of a panel to function as a radio box, and it is mostly fine, but I need the user to have the option of leaving both of them unchecked (I wish the user to select zero or one of the options). They are both unchecked when the form is displayed, but after the user checks one of them, it is impossible to revert to the original state. I would expect clicking the selected radio box would clear it (I vaguely remember this from my X/Motif days) but that doesn't seem to happen.
How do I program the radio buttons to allow both of them the be unchecked? Or should I be using some other control for this purpose?
There is no built in way to do what you're asking for. It is not that hard to do it our-self. Here's the sample code which shows how to do that.
C# version:
private void Initialize()
{
radioButton1.AutoCheck = false;
radioButton2.AutoCheck = false;
radioButton1.Click += radioButton_Click;
radioButton2.Click += radioButton_Click;
}
void radioButton_Click(object sender, EventArgs e)
{
RadioButton radio = (RadioButton)sender;
radio.Checked = !radio.Checked;
if (!radio.Checked)
{
return;
}
var otherRadios = radio.Parent
.Controls
.OfType<RadioButton>()
.Where(r => r != radio);
foreach (var r in otherRadios)
{
r.Checked = !radio.Checked;
}
}
Vb.net version:(Converted using http://converter.telerik.com/)
Private Sub Initialize()
radioButton1.AutoCheck = False
radioButton2.AutoCheck = False
AddHandler radioButton1.Click, AddressOf radioButton_Click
AddHandler radioButton2.Click, AddressOf radioButton_Click
End Sub
Private Sub radioButton_Click(sender As Object, e As EventArgs)
Dim radio As RadioButton = DirectCast(sender, RadioButton)
radio.Checked = Not radio.Checked
If Not radio.Checked Then
Return
End If
Dim otherRadios = radio.Parent.Controls.OfType(Of RadioButton)().Where(Function(r) r <> radio)
For Each r As var In otherRadios
r.Checked = Not radio.Checked
Next
End Sub
It should be simple if you think hatke.. Create your custom control
Imports System.ComponentModel
Public Class MyRadio
Inherits RadioButton
Private _permitted As Boolean = True
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
<Browsable(True)> _
Public Property Permitted() As Boolean
Get
Return _permitted
End Get
Set(ByVal value As Boolean)
_permitted = value
End Set
End Property
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
If _permitted Then MyBase.OnClick(e)
End Sub
End Class
HOW TO USE IT?
myRadio1.Permitted = False 'Assigning it to false will not allow you to select it.
You can use checkboxes, they can be checked and unchecked.
If you really want to uncheck a radio button then use the code below:
Private Sub RadioButton1_MouseDown(sender As Object, e As MouseEventArgs) Handles RadioButton1.MouseDown
If RadioButton1.Checked = True Then
Dim thr As New Threading.Thread(AddressOf unticker)
thr.Start()
End If
End Sub
Private Sub unticker()
Threading.Thread.Sleep(100)
Do Until RadioButton1.Checked = False
Invoke(Sub() RadioButton1.Checked = False)
Loop
End Sub
Use this for each radiobutton individually