VB How To Select All Controls Of Type And Set Text To Nothing - vb.net

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.

Related

Only show a certain count of textboxes in vb.net

I'm trying to make several TextBoxes visible and invisible, depending on the number in another textbox. In Fact I have 14(TextBox1, TextBox2, ...), this is my code so far:
Dim s As Integer = 0
While s > 14
s += 1
Dim txtBox As String = "TextBox" & CStr(s)
CObj(txtBox).Visible = False
End While
If txtBoxHowmany.Text = "" Then
Else
Dim s As Integer = 0
While s > txtBoxHowmany.Text
s += 1
Dim txtBox As String = "TextBox" & CStr(s)
CObj(txtBox).Visible = True
End While
End If
I created a list of text boxes and filled it in form Load. You can use this list in any method in your form.
In the Button.Click I used .TryParse to check the contents of TextBox7. I added a number range to the test with AndAlso's. AndAlso short circuits the If so that the following conditions will not be checked if the previous condition is False.
Next we use the .Take extension Function to get the text boxes we want to alter. A For Each loop actual changes the .Visible state.
Private TBoxes As New List(Of TextBox)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TBoxes.AddRange({TextBox1, TextBox2, TextBox3, TextBox4, TextBox5, TextBox6})
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim NumVisible As Integer
If Integer.TryParse(TextBox7.Text, NumVisible) AndAlso NumVisible > 0 AndAlso NumVisible < 15 Then
Dim VisibleBoxes = TBoxes.Take(NumVisible)
For Each tb In VisibleBoxes
tb.Visible = True
Next
Else
MessageBox.Show("Please enter a valid number.")
End If
End Sub
Design tip: use a spinner instead of a textbox.
Then you define the Minimum and Maximum values, while Value represents the currently-selected value. That makes the code more robust against incorrect input.
So the code could look like this:
dim s as integer = Me.spinner.Value
For i as Integer = 1 to s
Me.Controls("TextBox" & s.ToString).Visible = True
next
If value 5 is selected, then TextBox1 through TextBox5 become visible and you can continue with the rest and hide them as required.
Or a slightly more advanced example:
dim s as integer = me.spinner.Value
For Each ctl As Control In Me.Controls
Dim i as integer = 1
If TypeOf ctl Is TextBox Then
If ctl.Name.StartsWith("TextBox") Then
If ctl.Name = ("TextBox" & i.ToString()) ' eg TextBox1, TextBox5...
If i <= s Then ' counter <= value of spinner
ctl.Visible= True
Else
ctl.Visible= False
End If
End If
i += 1
End If
End If
Next
Here we loop on the form's child controls, look for those of Textbox type. i is an internal counter that is incremented at each occurrence of a TextBox control which name starts with 'TextBox'. If the control name starts with TextBox, and the rest of the string is a number <= spinner value, we set the Visible property to True. Otherwise, Visible is set to False.
So if the spinner value is 5, controls TextBox1 through TextBox5 should become visible, while the rest are to be hidden. The advantage to this approach is that the number of textboxes can be variable.
Disclaimer: untested code.
Update 09 March 2020
Here is a revised version that relies on a LINQ query to fetch a sorted list of textboxes in the form, assuming your controls are always named in the same pattern ie textbox1 through 14.
In theory this code could do the trick but it will not sort like I want ie textbox1 will be followed by textbox11, 12, 13, 14 and then textbox2.
Dim textboxes= From txt In Me.TableLayoutPanel1.Controls.OfType(Of TextBox)() _
Where txt.Name.StartsWith("TextBox") _
Order By txt.Name ' 1, 2, 14...
So I have tweaked the expression a little bit. I am assigning a variable textbox_number from LINQ to extract the number of the textbox:
Dim textboxes = From txt In Me.TableLayoutPanel1.Controls.OfType(Of TextBox)() _
Let textbox_number = Convert.ToInt32(txt.Name.Substring(7, txt.Name.Length - 7)) _
Where txt.Name.StartsWith("TextBox") _
Order By textbox_number ' 1, 2, 14...
This function is for demonstration purposes and should be improved to be made safer. It will work for your purpose though. By doing this trick I can perform a numeric sort so that that the controls are listed in the right order.
So if you select 5 in the spinner then controls 1 through 5 are made visible and the rest are hidden.
I have attached a screenshot. Note that I put all the textboxes in a TableLayoutPanel to improve presentation.
Probably, your controls are placed directly in the form and not in a container, then simply replace Me.TableLayoutPanel1.Controls with Me.Controls.
Public Class frmtextboxes
Private Sub butShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butShow.Click
Dim s As Integer = Me.spinner.Value ' number of textboxes to show
' LINQ query: get list of textboxes sorted by number
Dim textboxes = From txt In Me.TableLayoutPanel1.Controls.OfType(Of TextBox)() _
Let textbox_number = Convert.ToInt32(txt.Name.Substring(7, txt.Name.Length - 7)) _
Where txt.Name.StartsWith("TextBox") _
Order By textbox_number ' 1, 2, 14...
For Each ctl In textboxes
Console.WriteLine("TextBox found, name: " & ctl.txt.Name & "=> " & ctl.textbox_number)
If ctl.textbox_number <= s Then
Me.TableLayoutPanel1.Controls(ctl.txt.Name).Visible = True ' make control visible
Else
Me.TableLayoutPanel1.Controls(ctl.txt.Name).Visible = False ' hide control
End If
Next
End Sub
End Class

Check if Label text created in code contains specific string

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"

How would I use a for loop to edit multiple labels in Visual basic for visual studios

Here is my code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim randVal As Integer
Dim label As String
Dim val As Integer
Dim stringVal As String
For i As Integer = 1 To 256 Step 1
val = i
stringVal = CStr(val)
label = "Label" + stringVal
randVal = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1
label.BackColor = Color.Green
Next
End Sub
I get an error that string has no property BackColor.
How would I be able to edit all the strings without calling them individually?
The error message is correct: there isn't a property called BackColor on a string.
There is a BackColor property on Button, however, and it looks as if you're perhaps trying to set the background color of the Button object when it's clicked. If so, then you need to get hold of the Button object before you can set the color. The event handler has made this (moderately) easy, by passing the object into your handler as the parameter "sender". The only problem is that it's sent it as an object, not as a Button, so you first have to cast it to the type you want, like this:
Dim button As Button
button = DirectCast(sender, Button)
Then later on you can set the color:
button.BackColor = Color.Green
Also, if you want to set the text of the button, you have to set it using the button.Text property:
button.Text = "What I want to see on the button"
However, you're program is hard to follow. I can't see clearly from the code why you're executing a loop, or why you're setting values like randVal that aren't being used, and so it's hard to give concrete advice.
You are trying to access a property that does not exist.
The String type in Visual Basic has two properties. See here (https://msdn.microsoft.com/en-us/library/system.string_properties(v=vs.110).aspx)
If you are trying to change the background color of your label, then you need to reference your label name, which has that property.
For example: (I am assuming you want to change the text and color on your label)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim randVal As Integer
Dim labelText As String
Dim val As Integer
Dim stringVal As String
For i As Integer = 1 To 256 Step 1
val = i
stringVal = CStr(val)
labelText = "Label" + stringVal
randVal = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1
labelName.BackColor = Color.Green
Next
End Sub
Having said that, you can also use your label properties to change the text of your label.
labelName.Text = "Label" + stringVal
Here are some references
(How to change the text color. Simple?)
Also, here is a link to Label Properties (https://msdn.microsoft.com/en-us/library/system.windows.forms.label_properties(v=vs.110).aspx)
and your Buttons properties (https://msdn.microsoft.com/en-us/library/system.windows.forms.button(v=vs.110).aspx)
You managed to set the variable label to the name of your Label control, but not to the object itself. Now you need to get that Control object from its name.
VB6:
Me.Controls(label).BackColor = vbGreen
VB.Net:
Me.Controls(label).BackColor = Color.Green
However, you had an easier way to span you label controls and update their backgrounds:
Dim c as Control
For Each c In Me.Controls
If (TypeOf c Is Label) Then c.BackColor = Color.Green
Next c
If you want to reference Label1 thru Label256 in a loop, no matter which container they are in, then use Controls.Find():
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i As Integer = 1 To 256
Dim lbl As Label = Me.Controls.Find("Label" & i, True).FirstOrDefault
If Not IsNothing(lbl) Then
lbl.BackColor = Color.Green
End If
Next
End Sub

creating variables on loop with different names visual

I wan't to create a bunch of variables inside a While, each one with different names.
Here is what i tried:
Dim asd As Integer = 1
While asd < 5
Dim picturebox +asd As New Picturebox
End While
I want that it creates the Picturebox1 Picturebox2 ... and so on, but the "asd" variable won't evaluate and the code won't work. How could you create variables with different names in a loop with Visual Studio?
What I've done in the past is something like:
For i = 0 to 5
Dim t As New PictureBox()
t.Name = "PictureBox" & i
Me.Controls.Add(t)
Next
Dim picToChange = From r in Me.Controls Where Typeof(r) Is PictureBox AndAlso r.Name = "PictureBox1" Select r
If picToChange IsNot Nothing AndAlso picToChange.Any Then
'Do Something
End If
This is a very basic example and your linq would probably be more dynamic than the one I used but you should get the idea. In this case I'm assuming that you are just putting the PictureBoxes on the form, if this isn't the case then you will need to linq through whichever collection you are adding the controls to.
Edit #1:
As far as events are concerned you will need to add the handlers manually. So your code would become:
For i = 0 to 5
Dim t As New PictureBox()
t.Name = "PictureBox" & i
AddHandler t.Click, AddressOf(FunctionToHandleClick)
Me.Controls.Add(t)
Next
Dim picToChange = From r in Me.Controls Where Typeof(r) Is PictureBox AndAlso r.Name = "PictureBox1" Select r
If picToChange IsNot Nothing AndAlso picToChange.Any Then
'Do Something
End If
And the FunctionToHandleClick would look like this:
Private Sub FunctionToHandleClick(ByVal sender As Object, ByVal e As ClickEventArgs)
End Sub
Why don't you use an Array?
Dim pictureboxes(5) As PictureBox
For i As Integer = 0 To 5
pictureboxes(i) = New PictureBox()
Next

vb.net cycle through controls not working

I'm trying to cycle through the controls on a page that consists of textboxes and a dropdown and clear them.
When I debug, parent is the current page, value is equal to ASP.nameOfCurrentpage_aspx and
Type is equal to system.web.ui.page, but c has the value of ASP.site_master and type of system.web.ui.control. I also put in x to see how many controls it finds and x comes back as 1 even though there are 15 or so textboxes on the page. Is there a way I can force c to have the value of ASP.nameOfCurrentpage_aspx? Or is that not my problem? Any help is appreciated.
Protected Sub btnClear_Click(sender as Object, e as System.eventargs) Handles btnClear.Click
ClearForm(Page)
End Sub
Public Sub ClearForm(ByRef Parent As Control)
Dim c As Control
Dim x As Integer = Parent.Controls.Count
For Each c In Parent.Controls
If c.GetType.ToString = "System.Web.UI.HtmlControls.HtmlForm" Then
ClearForm(c)
ElseIf c.GetType() Is GetType(TextBox) Then
'is it a Text Box?
Dim t As TextBox = c
t.Text = ""
ElseIf c.GetType() Is GetType(DropDownList) Then
'is it a dropdown list?
Dim d As DropDownList = c
d.ClearSelection()
End If
Next
End Sub
The HTMLForm Control is probably nested, likely under a MasterPage. Either go fully recursive with your function or add a clause in your If Statement that looks for the Master Page. This is where breakpoints and the Watch Window are gold.
Ex:
ElseIf c.GetType.ToString = "ASP.MasterPageName_Master" Then
ClearForm(c)
Thank you every for your help. I didn't try all of the answers but I used them for ideas. This is what we came up with at work and it finds and clears all the controls on the page. We had to find the content place holder linked to the master site (cph). Again thanks for all the suggestions.
Public Sub ClearForm(ByRef Parent As Control)
Dim cph As System.Web.UI.WebControls.ContentPlaceHolder = Master.FindControl("MainBody")
Dim c As Control
Dim x As Integer = Parent.Controls.Count
For Each c In cph.Controls
If c.GetType.ToString = "System.Web.UI.HtmlControls.HtmlForm" Then
ClearForm(c)
ElseIf c.GetType() Is GetType(TextBox) Then
'is it a Text Box?
Dim t As TextBox = c
t.Text = ""
ElseIf c.GetType() Is GetType(DropDownList) Then
'is it a dropdown list?
Dim d As DropDownList = c
d.ClearSelection()
End If
Next
End Sub
It's been a while since I programmed anything in .NET with controls, MVC has spoiled me silly, or using VB.NET...
However I am thinking you will probably need to recurse through the stack of controls:
Protected Sub btnClear_Click(sender as Object, e as System.eventargs) Handles btnClear.Click
ClearForm(Page)
End Sub
Public Sub ClearForm(ByRef Parent As Control)
Dim c As Control
Dim x As Integer = Parent.Controls.Count
For Each c In Parent.Controls
If c.GetType.ToString = "System.Web.UI.HtmlControls.HtmlForm" Then
ClearForm(c)
ElseIf c.GetType() Is GetType(TextBox) Then
'is it a Text Box?
Dim t As TextBox = c
t.Text = ""
ElseIf c.GetType() Is GetType(DropDownList) Then
'is it a dropdown list?
Dim d As DropDownList = c
d.ClearSelection()
ElseIf c.Controls != null ' Does VB.NET support nulls? I forget
ClearForm(c.Controls)
End If
Next
End Sub