Accessing textboxes created at runtime
I have a program in which I create labels as follows:
Code:
r = 137
Dim j As Integer
For j = 1 To Bcount
Dim lbl As New Label
lbl.Name = "lbl" & j
lbl.Text = Branch(j)
lbl.Location = New Point(1095, r)
Controls.Add(lbl)
r = r + 30
Next
This gives me a 'column' of 42 Branch names
I then created three 'columns of textboxes alongside the labels using:
Code:
r = 134
Dim t As Integer = 100
For j = 1 To Bcount
Dim tb1 As New TextBox
Dim tb2 As New TextBox
Dim tb3 As New TextBox
tb1.Name = "tb" & t
tb1.Tag = Branch(n)
tb1.Size = New Size(40, 20)
tb2.Name = "tb" & t + 1
tb2.Size = New Size(40, 20)
tb3.Name = "tb" & t + 2
tb3.Size = New Size(40, 20)
tb1.Location = New Point(1200, r)
Me.Controls.Add(tb1)
tb2.Location = New Point(1250, r)
Me.Controls.Add(tb2)
tb3.Location = New Point(1300, r)
Me.Controls.Add(tb3)
r = r + 30
t = t + 3
Next
My question is; how do I now access these textboxes to input data from a product usage txt file?
In other words:
The first label is for a branch called Abel. I want to put that branch's usages of a particular product in the adjacent textbox. The index for the usage file is (a). The reason for three textboxes adjacent to each label is to get the usage figures for each of the past three months. My problem is that I can't seem to access the individual textboxes by name.
Using the above code I thought I'd named the first textbox as "tb1" + 100, but it doesn't seem to be that simple and I'm stuck.
Just ask if you need additional information.
Re: Accessing textboxes created at runtime
You could create them into a "list(of textbox)" instead:
Code:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim tb1 As New List(Of TextBox)
Dim tb2 As New List(Of TextBox)
Dim tb3 As New List(Of TextBox)
Dim j As Integer
For j = 0 To 41
tb1.Add(New TextBox)
With tb1
'tag, size, etc.
End With
Me.Controls.Add(tb1(j))
tb2.Add(New TextBox)
With tb1
'....
End With
Me.Controls.Add(tb2(j))
Next
'random stuff showing how to access them
tb1(3).Visible = False
tb3(0).Text = "abc"
End Sub
End Class
Re: Accessing textboxes created at runtime
you did name the textbox tbl1100... what you do NOT have is name the object tbl1100 ... what you did was set the .Name property to "tbl1100" ...
Since there isn't an actual object named tbl1100, you can't use tbl1100.Text to access it. You can access it though through the controls collection: Me.Contols("tbl1100").Text ...
-tg
Re: Accessing textboxes created at runtime
Since you are creating the textboxes, I'd avoid going through the Controls collection. Either put them in some lists, as vbfbryce showed, or consider a Dictionary(of something, textbox). The key could be a variety of things, depending on what seemed best. For example, you could use the textbox name, but you could also use an integer. For example, you might say that all textboxes in the first column are 100 to N, all in the second column are 200 to M, and all in the third column are 300 to T. So, if there are 20, then the first column would be 100 - 119, the second column would be 200 - 219, and the third column would be 300 - 319.
The Dictionary object is a pretty convenient collection for associating some item with some key for quick and easy lookup.
Re: Accessing textboxes created at runtime
Quote:
Originally Posted by
vbfbryce
You could create them into a "list(of textbox)" instead:
Code:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim tb1 As New List(Of TextBox)
Dim tb2 As New List(Of TextBox)
Dim tb3 As New List(Of TextBox)
Dim j As Integer
For j = 0 To 41
tb1.Add(New TextBox)
With tb1
'tag, size, etc.
End With
Me.Controls.Add(tb1(j))
tb2.Add(New TextBox)
With tb1
'....
End With
Me.Controls.Add(tb2(j))
Next
'random stuff showing how to access them
tb1(3).Visible = False
tb3(0).Text = "abc"
End Sub
End Class
I tried this using
Code:
r = 134
Dim tb1 As New List(Of TextBox)
Dim tb2 As New List(Of TextBox)
Dim tb3 As New List(Of TextBox)
'Dim j As Integer
For j = 1 To Bcount
tb1.Add(New TextBox)
With tb1
Size = New Size(40, 20)
Location = New Point(1200, r)
End With
Me.Controls.Add(tb1(j))
tb2.Add(New TextBox)
With tb2
Size = New Size(40, 20)
Location = New Point(1250, r) '....
End With
Me.Controls.Add(tb2(j))
tb3.Add(New TextBox)
With tb3
Size = New Size(40, 20)
Location = New Point(1300, r) '....
End With
Me.Controls.Add(tb3(j))
r = r + 30
Next
but got an error "An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
Additional information: Index was out of range. Must be non-negative and less than the size of the collection."
This was at line: Me.Controls.Add(tb1(j))
Bcount holds the number of branches (currently 42)
Re: Accessing textboxes created at runtime
Yeah. All arrays are 0 based in .NET. Therefore, when you add the first textbox to the list, it is added at tb1(0). So, in your code, you are trying to add tb1(j), but j starts at 1 rather than 0. So, you add the first textbox which is at tb1(0), then you try to add the textbox located at tb1(1), which doesn't exist, yet.
The easiest thing to do is to make the loop:
From j = 0 to BCount -1
Re: Accessing textboxes created at runtime
Probably a stupid question, but I'm going to ask anyways since no one else has ... by textboxes? Why not use a grid?
-tg
Re: Accessing textboxes created at runtime
Thanks for that. It certainly got round the issue; however, vbfBryce said that I could access using
Code:
tb1(1).Visible = True
tb1(1).Text = "abc"
but I can't see them on the form.
Re: Accessing textboxes created at runtime
Quote:
Originally Posted by
techgnome
Probably a stupid question, but I'm going to ask anyways since no one else has ... by textboxes? Why not use a grid?
-tg
Not a stupid question; but the simple answer is that I'm still learning and wouldn't know where to start!!
Re: Accessing textboxes created at runtime
You forgot to put the "." in front of your properties, so you would be changing the Size and Location of the Form, I would think. Perhaps the Size is invalid for a form so you don't notice?
Or if the code is in the Form_Load event, then it could have cause an exception which is silently swallowed, so your code just bails and you don't create any of the controls (in addition to not properly sizing and locating them).
You could use SetBounds to set the Location and Size in one statement.
Code:
tb1.Add(New TextBox)
With tb1
.Size = New Size(40, 20)
.Location = New Point(1200, r)
p.s. looking back, I see the code was in the form load, so you probably got an exception and the form was shown without running any of the other code in your form load after the exception.
Re: Accessing textboxes created at runtime
And to correct what I posted in #2:
Code:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim tb1 As New List(Of TextBox)
Dim tb2 As New List(Of TextBox)
Dim j As Integer
For j = 0 To 9 'creates 10
tb1.Add(New TextBox)
With tb1(j) 'forgot the index in post #2 ***
.Left = 10 + (j * 50)
.Width = 50
'etc.
End With
Me.Controls.Add(tb1(j))
Next j
End Sub
Re: Accessing textboxes created at runtime
To expand on something passel mentioned: There's an issue you need to be aware of with the Load event. Due to an internal debate between the OS and VS groups in MS, any exceptions thrown in the Load event on a 64-bit version of Windows, will be quietly swallowed. The code will simply stop running on the line that threw the exception. You won't get any message or warning, code will just exit the Load event. This can cause really strange behavior and can totally confuse people.
Re: Accessing textboxes created at runtime
Also, in order to access the lists of Textbox later, the lists shouldn't be declared in the Form1_Load method.
Declare them at the class level.
Code:
Public Class Form1
Private tb1 As New List(Of TextBox)
Private tb2 As New List(Of TextBox)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim j As Integer
For j = 0 To 9 'creates 10
tb1.Add(New TextBox)
With tb1(j) 'forgot the index in post #2 ***
.Left = 10 + (j * 50)
.Width = 50
'etc.
End With
Me.Controls.Add(tb1(j))
Next j
End Sub
'...etc
End Class