Dynamically Creating Control Arrays in VB.NET 2003
Posted on 2007-04-05
I have seen a lot of questions and solutions here about the issue of not being able to use control arrays in VB.NET the way we used to be able to do it in VB6. After much research and playing around with some examples I found here on Experts-Exchange, I decided I should share what I discovered so everyone can benefit. I am assigning points to this simply because I am a newbie to VB.NET and I would appreciate any feedback that could enhance what I have put together or if someone can determine that there are problems with what I did and are able to offer fresh ideas.
For my application I have a MS Access database table for digital Outputs (used to turn things on and off in the physical world). For each project we build, the number of digital outputs is different. The database table contains multiple fields but the two most important are the 'SensorID' and the "NameLong". The 'SensorID' field is the PK in this table. The 'NameLong' field is the descriptive text of the function of what the checkbox does. For the user to better understand what these do I need to provide both the 'SensorID' and the 'NameLong' as the text for the checkbox. What I needed to do was create a checkbox on a specific tab on a form for each of the digital Outputs in the database table.
At Form Level I have this:
Dim cbx() As CheckBox
I then have the following subroutine in the form code that gets the data from the database table and dynamically creates the checkboxes and sets their properties. Most of the code below should be self explanatory but I have added some comments:
Public Sub SetupICdigOut()
Dim i As Integer
' constr is the connection string for the system database
' constr is defined in ProjConst.vb code
Dim conn As New OleDb.OleDbConnection(constr)
Dim strSql As String
strSql = "SELECT SensorID, NameLong, NameShort, SlotNumber, ChannelNumber, OrderNum "
strSql = strSql & "FROM DIG_OUT_Definition ORDER BY OrderNum"
Dim da As New OleDb.OleDbDataAdapter(strSql, conn)
Dim dt As New DataTable
Dim digOutCount As Integer = dt.Rows.Count 'how many dig outputs are there?
ReDim cbx(digOutCount) 'set array dimension based on the number of Dig Outputs in database table
i = 0 'cbx(0) to cbx(numOfCheckBoxesNeeded-1)
For Each dr As DataRow In dt.Rows
cbx(i) = New CheckBox
cbx(i).Name = "chkBx_" & CStr(dr.Item("SensorID")) 'give it a name based on the PK in database
cbx(i).Left = 50 'set the LEFT position of the checkbox
cbx(i).Top = 10 + i * 30 'set the TOP pos. based on which checkbox it is
cbx(i).Text = CStr(dr.Item("SensorID")) & " " & CStr(dr.Item("NameLong")) 'create the TEXT by combining the SensorID and NameLong fields with a space in between
cbx(i).Width = Len(cbx(i).Text) * 7 'multiply num of chars by 7 to get proper width
' I multiplied by 7 because it was the smallest number that would allow a single character to fit based
'on the default font - for larger or BOLD fonts 7 would need to be increased
cbx(i).Visible = True 'make the control visible
cbx(i).Tag = i 'use Tag as a way of addressing the specific checkbox
'it appears from my testing so far that .Tag works like an INDEX in this case.
Me.TabDigOut.Controls.Add(cbx(i)) 'add this specific checkbox to the specific tab on the form
AddHandler cbx(i).CheckedChanged, AddressOf cbx_CheckedChanged 'AddHandler
i = i + 1 ' increment i by one for the next subscript
Finally, I needed to see how the system reacted to checking and un-checking the checkboxes so I tried a few things that just popped up message boxes. Most of these are commented out below but they do work. The stuff in the IF-ELSE-ENDIF is just there for my debugging purposes for now. I will add the actual code later as I continue my development. But as you can see, this does work.
Private Sub cbx_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
'MsgBox(sender.text) ' This will provide the TEXT of the CheckBox
'MsgBox(sender.name) ' This will provide the NAME of the CheckBox
'MsgBox(sender.tag) ' This will provide the TAG (or 'INDEX') of the CheckBox)
'Any code can go in the IF - ELSE - ENDIF statements below as required for your application
If cbx(sender.tag).Checked Then
MsgBox("Check Box " & sender.tag & " " & "Named " & sender.name & " and an Index # of " & sender.tag & " has been CHECKED")
MsgBox("Check Box " & sender.tag & " " & "Named " & sender.name & " and an Index # of " & sender.tag & " has been UN-CHECKED")
I look forward to any comments or feedback regarding this as I know this has been troubling a lot of people who are migrating from VB6 and are looking to dynamically create control arrays.
Thanks for your time and all of your previous help.