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
Related
I am trying to change different values in a for loop in vb.net. However, I couldn't find how to change the numbered boolean variables.
Dim txt1 As Boolean = False
Dim txt2 As Boolean = False
i = i + 1
If i < 9 Then
'I tried to do:
Me.Controls("txt" & i.ToString) = True
txt(i) = True
End If
How can I change the numbered boolean variables and what is the most efficient way to it?
The right way to access the booleans is in an array or a list.
Using the example of the question:
Dim bool(2) As Boolean
i = i + 1
If i < 9 Then
bool(i) = True
End If
I guess you want to iterate over the TextBox controls and then change the property of TextBox.enabled.
You can try the following methods.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each c As Control In Me.Controls
If c.GetType.ToString() = "System.Windows.Forms.TextBox" Then
c.Enabled = True 'You can change the TextBox Controls. Enabled to False too.
c.Text = c.Name.ToString
End If
Next
End Sub
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
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'm new to VB.NET and have been struggling all afternoon with something. I've found similar questions on the forum but none of them seemed to describe my problem exactly. I'm fairly sure that I'm missing something very basic.
I have made a main form which currently holds only one button which purpose is to open up a second form and close the main form. Based on the settings the user will select on the 2nd form the first form might have to be adapted to match with the new settings. But the problem occurs even before that.
The 'settings' form has 15 textboxes which I drew onto the form in development mode. They are called ID1, ID2,..,ID15. The values which I want to display in there are saved in an array:
Dim ids(15) as integer
Next, I created a module to simulate what you could call a control array as I used to use them in VB6.
Public sources() As TextBox = [frmSettings.ID1, frmSettings.ID2, //and so on
I did this to be able to iterate through all the 15 textboxes:
For i = 0 To 14
Sources(i).Text = ids(i + 1)
Next
Then I added on the main form this code to the Button1_Click() event:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
frmSettings.Show()
Me.Close()
End Sub
I did the same thing for the 'exit ' button on the frmSettings form.
This seems to work, but only once. I launch the application, push the button and frmSettings pops up and shows all the values from the array in the textboxes. When I push the 'close' button, I return to the main page.
So far so good, but if I try to return to frmSettings a second time, all the textboxes remain blank as if the code I added to the form never gets executed.
Any help would be greatly appreciated!
First, make sure the array that holds your data is accessible to both forms:
Module Module1
Public ids(15) As Integer
End Module
There should not be a declaration for "ids" in either form.
Next, make frmSettings itself responsible for loading and saving the data:
Public Class frmSettings
Private Sub frmSettings_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim matches() As Control
For i As Integer = 0 To 14
matches = Me.Controls.Find("ID" & (i + 1), True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is TextBox Then
Dim TB As TextBox = DirectCast(matches(0), TextBox)
TB.Text = ids(i)
End If
Next
End Sub
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim valid As Boolean = True
Dim matches() As Control
For i As Integer = 0 To 14
matches = Me.Controls.Find("ID" & (i + 1), True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is TextBox Then
Dim TB As TextBox = DirectCast(matches(0), TextBox)
Dim value As Integer
If Integer.TryParse(TB.Text, value) Then
ids(i) = value
Else
MessageBox.Show(TB.Name & ": " & TB.Text, "Invalid Value", MessageBoxButtons.OK, MessageBoxIcon.Warning)
valid = False
End If
End If
Next
If valid Then
Me.Close()
End If
End Sub
End Class
Public Class Form1
Private Function AllEnabled(ByVal b As Boolean) As Boolean
For i As Integer = 0 To 2
Dim c As CheckBox = CType(Me.Controls("CheckBox" & i.ToString), CheckBox)
c.Enabled = b
Next
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Call AllEnabled(False)
End Sub
End Class
getting error with highlight in b at c.Enabled = b
(Object reference not set to an instance of an object.)
but when i use checkbox1.enabled = b instead of c.enabled = b works fine.
so as i see the wrong not with b right ?
& how can i fix this ?
Try this:
For Each ctl In Me.Controls
If TypeOf ctl Is CheckBox Then
ctl.Enabled = b
End If
Next
Two possible reasons. Your for-loop creates this control names:
"CheckBox0"
"CheckBox1"
"CheckBox2"
Maybe you want 1-3 or 0-1 instead.
Maybe you want to find your checkbox recursively, then you can use Find:
For i As Integer = 0 To 2
Dim ctrl = Me.Controls.Find("CheckBox" & i.ToString, True)
If ctrl.Length <> 0 Then
ctrl(0).Enabled = b 'Find returns an aray'
End If
Next
Side-note: 2013 i would not use this VB6 style anymore:
Call AllEnabled(False)
but just
AllEnabled(False)