I have several labels and textboxes created and the number of them depends on what the user types into a textbox, i.e. 5 typed in so there would be 5 labels and 5 textboxes.
I can recursively search out all labels which name is "myLabel" & var, var = number 1 through 5 in this example.
What i have is a context menu for the labels with 3 items. Item 1 changes the label text to whatever the user wants, numbers, letters, and/or symbols. Item 2 and 3 is what i am having trouble with.
Item 2 needs to change the label text to D1 the first time it is initiated, then it needs to change it to D2 the second time and if a third time is invoked an error should not let them continue.
Item 3 is the same as 2, except the text should be S1 and S2 respectively.
What I have so far is this, however i keep getting stuck in a loop or it doesn't change the label.text to what i want. Any help is appreciated
Private Sub lblMenuItem3_Click()
label = lblContextMenu.SourceControl.Name
For Each control As Control In Me.Controls
If TypeOf control Is Label Then
Dim myLabel As Label = DirectCast(control, Label)
Dim str As String = myLabel.Text
'If myLabel.Text = "S1" Then
If LCase(str).Contains(LCase("S1")) Then
'MessageBox.Show("That string is in here!")
Me.Controls.Item(label).Text = "S2"
Else
'MessageBox.Show("The string is not in here!")
Me.Controls.Item(label).Text = "S1"
End If
Else
Me.Controls.Item(label).Text = "S1"
'End If
End If
Next
'Me.Controls.Item(label).Text = "S1"
'Me.Controls.Item(label).Text = "S2"
End Sub
EDIT1:
This code is partially working as i need it to, but for some reason it runs the sub the number of times equal to the number of labels on the form and I'm not sure why
Private Sub lblMenuItem3_Click()
label = lblContextMenu.SourceControl.Name
Dim s1lbl As Boolean = False
Dim s2lbl As Boolean = False
For Each control As Control In Me.Controls
If TypeOf control Is Label Then
Dim myLabel As Label = DirectCast(control, Label)
Dim str As String = myLabel.Text
If LCase(str).Contains(LCase("S1")) Then
s1lbl = True
Exit For
ElseIf LCase(str).Contains(LCase("S2")) Then
s2lbl = True
Exit For
Else
Continue For
End If
End If
Next
If s1lbl = False AndAlso s2lbl = False Then
Me.Controls.Item(label).Text = "S1"
Exit Sub
End If
If s1lbl = True AndAlso s2lbl = False Then
Me.Controls.Item(label).Text = "S2"
Exit Sub
End If
If s1lbl = False AndAlso s2lbl = True Then
MessageBox.Show("Too many Shallow points, only 2 allowed.")
Exit Sub
End If
End Sub
this is the code:
Private Sub TextBoxABPts_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBoxABPts.KeyPress
For i = 1 To TextBoxABPts.Text
lbl1 = New Label()
lbl1.Location = New Point(2, 165 + 25 * (i - 1))
lbl1.Name = "myLabel" & i
lbl1.Text = i
Me.Controls.Add(lbl1)
AddHandler lblMenuItem1.Click, AddressOf lblMenuItem1_Click
AddHandler lblMenuItem2.Click, AddressOf lblMenuItem2_Click
AddHandler lblMenuItem3.Click, AddressOf lblMenuItem3_Click
lblContextMenu.MenuItems.Add(lblMenuItem1)
lblContextMenu.MenuItems.Add(lblMenuItem2)
lblContextMenu.MenuItems.Add(lblMenuItem3)
lbl1.ContextMenu = lblContextMenu
Next i
TextBoxABDist.Focus()
End If
I think this should help you out:
Add your menu items to the lblContextMenu outside the for loop where ever you create the lblContextMenu
lblContextMenu.MenuItems.Add("click1", New System.EventHandler(AddressOf Me.lblMenuItem1_Click1))
lblContextMenu.MenuItems.Add("click2", New System.EventHandler(AddressOf Me.lblMenuItem1_Click2))
lblContextMenu.MenuItems.Add("click3", New System.EventHandler(AddressOf Me.lblMenuItem1_Click3))
Then in your for loop just add the contextmenu to the labels:
For i As Integer = 1 To TextBoxABPts.Text
Dim lbl1 = New Label()
lbl1.Location = New Point(2, 165 + 25 * (i - 1))
lbl1.Name = "myLabel" & i
lbl1.Text = i
Me.Controls.Add(lbl1)
lbl1.ContextMenu = lblContextMenu
Next i.
Then as an example your menu click sub might look something like this:
Private Sub lblMenuItem1_Click1(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim mi As MenuItem = CType(sender, MenuItem)
Dim menu As ContextMenu = mi.GetContextMenu()
Dim lbl As Label = CType(menu.SourceControl, Label)
lbl.Text = mi.Text
End Sub
You'll need to combine this with your current ifelse logic.
This:
If LCase(str).Contains(LCase("S1")) Then
'MessageBox.Show("That string is in here!")
Me.Controls.Item(label).Text = "S2"
Else
'MessageBox.Show("The string is not in here!")
Me.Controls.Item(label).Text = "S1"
End If
Should be this:
If LCase(str).Contains(LCase("S1")) Then
'MessageBox.Show("That string is in here!")
myLabel.Text = "S2"
ElseIf LCase(str).Contains(LCase("S2"))
'MessageBox.Show("Bad Stuff!")
' Do your S3 error things here
Else
'MessageBox.Show("No S Value Found!")
myLabel.Text = "S1"
End If
Without the ElseIf structure, you will alternate between setting it as S1 or S2, and there is no other option. With the structure in place you check for all possibilities and it shouldn't loop.
You need to use the proper signature in your method. It should look like this.
Label1_Click(sender As Object, e As EventArgs)
Then you can cast sender to a Label and set the text.
Ctype(sender, Label).Text = "S1"
Related
im coding a sequence guesser game and id like to program it so whenever you enter a number wrong it resets all the labels how would i universally select the label type and make the text = Nothing
i tried this but it didnt work
Thanks
Imports System.Media
Public Class comboForm
Dim score As Integer = 0
Dim winsound As New SoundPlayer(My.Resources.winsound_wav)
' 1 7 8 8 4 7 1 5 5
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
If score = 0 Then
score += 1
lblStage1.Text = "1"
ElseIf score = 7 Then
score += 1
lblStage7.Text = "7"
Else
score = 0
For Each lbl In tlpMain.Controls.OfType(Of Label)()
lbl.Text = Nothing
Next
End If
End Sub
End Class
For Each lbl In Me.Controls.OfType(Of Label)()
'...
Next
The OfType method is basically a filter by type on a list. That code is pretty much the equivalent of this:
For Each ctrl In Me.Controls
If TypeOf ctrl Is Label Then
Dim lbl = DirectCast(ctrl, Label)
'...
End If
Next
or this:
For Each ctrl In Me.Controls
Dim lbl = TryCast(ctrl, Label)
If lbl IsNot Nothing Then
'...
End If
Next
Obviously this code will only access Labels directly on the form, because it uses the form's Controls collection. Use the Controls collection of the appropriate container, e.g. a Panel to access controls in that container.
I have this code:
Dim val1,val2,val3,val4,val5, ... ,val20 As String
If Combobox1.SelectedIndex = 0 Then
val1=">"
else
val1="<"
end if
If Combobox2.SelectedIndex = 0 Then
val2=">"
else
val2="<"
end if
How can I loop this? There are 20 Combo boxes. Please help! Thanks
To loop through the controls on the form, use Me.Controls. And to check the type of the control, use Control.GetType.Name.
The problem is that separate variables like val1,val2,val3...etc cannot be easily used in a loop, so I recommend changing them to a list.
Dim val As New List(Of String)
For Each MyControl In Me.Controls
If MyControl.GetType.Name = "ComboBox" Then
Dim MyComboBox As ComboBox = CType(MyControl, ComboBox)
If MyComboBox.SelectedIndex = 0 Then
val.Add(">")
Else
val.Add("<")
end if
End If
Next
So, here are some looping sequences for you. disclaimer - code is not tested, could be bugs but logical layout should be correct
Private _numOfControls As Integer = 20
Private _variables As New Dictionary(Of String, String)(_numOfControls)
Private Sub Setup()
For i as integer = 1 To _numOfControls
Dim cboName As String = "cbo" & i
Dim cbo As New ComboBox()
cbo.Name = cboName
cbo.SelectedIndex = 0
' Add cbo location according to your logic here
container.Controls.Add(cbo) ' container - any control or form that hosts cbo
_variables.Add(cboName, ">")
AddHandler cbo.SelectedIndexChanged, AddressOf OnCboSelectedIndexChanged
Next
End Sub
' If you do this way, your control-related variable will have appropriate equality sign without need for iteration
Private Sub OnCboSelectedIndexChanged (sender As Object, e As EventArgs)
Dim cbo As ComboBox = CType(sender, ComboBox)
myDict(cbo.Name) = If(cbo.SelectedIndex = 0, ">", "<")
End Sub
' But if you do not want to do in the above^^ way, you can iterate dictionary
Private Sub FromDictionaryToCbo()
' Here you can't use for-loop on dictionary because your dictionary will be mutating. So lets iterate keys
For Each k As String In _variables.Keys.ToArray())
_variables(k) = If(CType(container.Find(k, True), ComboBox).SelectedIndex = 0, ">", "<")
Next
End Sub
' And iterating combo boxes would be something similar as another answer here
' But we use our naming convention to bypass other controls
Private Sub FromCboToDictionary()
Dim c As Control
For i As Integer = 1 To < _numOfControls
Dim key As String = "cbo" & i.ToString()
'We don't know, may be there some other combo boxes are there, so we use our naming convention instead of control type
c = container.Find(key, True)
If c IsNot Nothing Then
_variables(key) = If(CType(c, ComboBox).SelectedIndex = 0, ">", "<")
end If
Next
End Sub
I am new to VB and run into some problems.
I have created sub routine that will automatically add a control to a panelcontrol each time i click on the button, so it can create as many as i want.
Here is the code for the subroutine.
Private Sub CreateControl()
'CREATE TEXTBOX ITEMNO
Dim i_Itemno As Integer = TextEditItemno.Length
ReDim Preserve TextEditItemno(i_Itemno)
TextEditItemno(i_Itemno) = New TextEdit
With TextEditItemno(i_Itemno)
.Name = "Txtitemno" & i_Itemno.ToString()
If TextEditItemno.Length < 2 Then
.SetBounds(0, 0, 32, 20)
Else
.Left = TextEditItemno(i_Itemno - 1).Left
.Top = TextEditItemno(i_Itemno - 1).Top + TextEditItemno(i_Itemno - 1).Height + 4
.Size = TextEditItemno(i_Itemno - 1).Size
End If
.Tag = i_Itemno
End With
AddHandler TextEditItemno(i_Itemno).TextChanged, AddressOf TextEditItemno_TextChanged
PanelControl5.Controls.Add(TextEditItemno(i_Itemno))
'CREATE TEXTBOX PRICE
Dim i_Price As Integer = TextEditPrice.Length
ReDim Preserve TextEditPrice((i_Price))
Dim PriceX As Int16 = LblHarga.Location.X
TextEditPrice(i_Price) = New TextEdit
With TextEditPrice(i_Price)
.Name = "Txtprice" & i_Price.ToString()
If TextEditSatuan.Length < 2 Then
.SetBounds(PriceX, 0, 70, 20)
Else
.Left = TextEditPrice(i_Price - 1).Left
.Top = TextEditPrice(i_Price - 1).Top + TextEditPrice(i_Price - 1).Height + 4
.Size = TextEditPrice(i_Price - 1).Size
End If
.Tag = i_Price
End With
AddHandler TextEditPrice(i_Price).TextChanged, AddressOf TextEditPrice_TextChanged
PanelControl5.Controls.Add(TextEditPrice(i_Price))
End Sub
And i call it in a button click.
Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click
CreateControl()
End Sub
Now what i am looking for is how to loop and get the value of those textboxes no matter how many textboxex i have create.
For i As Integer = 0 To TextEditItemno.Length - 1
' code to get the value of each textbox
Next
Thank you
This code goes in to your loop and gets the value of each textbox based on i.
Dim Text as String = TextEditItemno(i).Text
You may also be better served by using a List(of Textbox) rather than an array of textboxes. You don't need to worry about redimming the array, you can just do MyListOfTextboxes.Add(TheNewTextBox). You can still retrieve the value of each textbox the same way as the array.
I have a DataGridView in my form that has a ComboBoxColumn that holds a hard-coded list of plants. I also give the user the option to add other plants if "Other" is selected.
When the user selects "Other", he puts the new grass name in the message box.
However, after OK is clicked, the new name isn't added to the combobox. (The value for Plant Spacing is added programmatically)
Only by clicking on another cell in the table is the new name added.
How can I get the combobox to update without needing to losing focus?
Here is the code I'm using when the Combobox is clicked
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
CB = TryCast(e.Control, System.Windows.Forms.ComboBox)
If CB IsNot Nothing Then
RemoveHandler CB.SelectedIndexChanged, AddressOf DGVComboIndexChanged
AddHandler CB.SelectedIndexChanged, AddressOf DGVComboIndexChanged
End If
' Other event handlers removed and added here
End Sub
Private Sub DGVComboIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
' Do what you like with the current ComboBoxCell.
'System.Windows.Forms.MessageBox.Show(String.Format( _
'"The SelectedIndex was changed in ComboBoxCell: {0}" & _
'Environment.NewLine & _
'"The current item is: {1}", _
'Me.DataGridView1.CurrentCellAddress.ToString(), _
'CB.SelectedItem.ToString()))
Dim TryAgain As Boolean = True
Dim Letters As String = "abcdefghijklmnopqrstuvwxyz1234567890"
Dim ComboColumn As System.Windows.Forms.DataGridViewComboBoxColumn
ComboColumn = DataGridView1.Columns(0)
Try
If CB.SelectedItem.ToString = "Other" Then
While TryAgain
OtherGrass = Microsoft.VisualBasic.InputBox("Enter the alternate plant name", "Other plant", "")
If OtherGrass = "" Then
'return the cell to ""
DataGridView1.CurrentRow.Cells(0).Value = ""
Exit Sub
End If
For i As Integer = 1 To Len(Letters)
If InStr(LCase(OtherGrass), Mid(Letters, i, 1)) > 0 Then
TryAgain = False
Exit For
End If
Next
For i As Integer = 0 To ComboColumn.Items.Count - 1
If LCase(OtherGrass) = LCase(ComboColumn.Items.Item(i).ToString) Then
TryAgain = True
System.Windows.Forms.MessageBox.Show("This plant has already been added.")
End If
Next
End While
'ReDim Preserve Grasses(Grasses.GetUpperBound(0) + 1)
'Grasses(Grasses.GetUpperBound(0)) = OtherGrass
ComboColumn.Items.Add(OtherGrass)
End If
If DataGridView1.CurrentRow.Cells(1).Value Is Nothing Then
DataGridView1.CurrentRow.Cells(1).Value = txtSpacMult.Text
End If
'If CB.SelectedItem.ToString <> "" Then
' For i As Integer = 1 To DataGridView1.Columns.Count - 2
' Dim temp As Boolean = Me.DataGridView1.Rows(DataGridView1.CurrentRow.Index).Cells(i).ReadOnly
' Me.DataGridView1.Rows(DataGridView1.CurrentRow.Index).Cells(i).ReadOnly = False
' temp = Me.DataGridView1.Rows(DataGridView1.CurrentRow.Index).Cells(i).ReadOnly
' Next
'End If
EnableRun()
Catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.Message)
End Try
End Sub
Instead of:
ComboColumn.Items.Add(OtherGrass)
Put:
CB.Items.RemoveAt(CB.Items.Count - 1)
CB.Items.Add(OtherGrass)
CB.Items.Add("Other")
CB.SelectedItem = OtherGrass
You should have the new plant added and selected, and the "Other" entry moved to the end.
I have an UserControl and wish to add it to a TabPage Inside another TabPage but get NullReferenceException instead.
My code
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim MyControl As New TimerPanel
Dim Ubicacion As Point
Ubicacion.X = 274
Ubicacion.Y = 100
With MyControl
.Name = "Timer0"
.NombreTimerTxt.Text = "Timer GPS"
.TimerBox.Text = "Timer 00"
.Parent = Me '.TabControl3.TabPages("Timers")
.Location = Ubicacion
.Visible = True
End With
Me.TabControl3.TabPages("Timers").Controls.Add(MyControl) 'Error here
'Me.TabControl1.TabPages("Timers").Controls("Timer0").Location = Ubicacion
End Sub
The IDE say that I must declare it using the word "New", but I already did it on the first code line.
Another thing, If I iterate this code changing the name and coordinates I will get independent controls or when I change one all do the same?
My form looks like this.
Thanks to LarsTech I solve the problem and add several UserControls to my TabPage using the following code
Dim X As Integer = 4
Dim Y As Integer = 0
For XTimer As Integer = 0 To 15
Dim MyControl As New TimerPanel
Dim Ubicacion As Point
Ubicacion.X = X
Ubicacion.Y = Y
With MyControl
.Name = "Timer" & XTimer.ToString
.NombreTimerTxt.Text = "Timer GPS"
.TimerBox.Text = "Timer " & XTimer.ToString
.Parent = Me
.Location = Ubicacion
.Visible = True
End With
TimersTab.Controls.Add(MyControl)
Y += 51
If XTimer = 9 Then 'Start column 2
X = 344
Y = 0
End If
Next
I hope someone finds this useful; bye.