Solved

Dynamically Creating Control Arrays in VB.NET 2003

Posted on 2007-04-05
5
874 Views
Last Modified: 2012-06-22
Hi,

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
        da.Fill(dt)

        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
        Next
    End Sub

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")
        Else
            MsgBox("Check Box " & sender.tag & "  " & "Named " & sender.name & " and an Index # of " & sender.tag & " has been UN-CHECKED")
        End If
    End Sub

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.

Charlie
0
Comment
Question by:charlieb01
  • 2
  • 2
5 Comments
 
LVL 24

Expert Comment

by:Jeff Certain
ID: 18859188
Well, the first thing I'd do is leverage the System.Collections.Generic namespace to replace those nasty non-type-safe arrays. For example, replace Dim cbx() As CheckBox with Private cbx as New List(Of CheckBox). This gives you design-time type-checking to make sure you're only putting checkboxes in that "array". It also alleviates the need to redim, since you can simply Add/Remove the checkboxes.

I'd also consider adding a DataTable property that I set from outside the control. You'd be able to move all your database access code to a data access alyer than, and the reusability of the control would be improved, since you wouldn't be bound to a specific table in a specific database. (Or, for that matter, even a particular database type, since you can use data providers against multiple database engines to provide a datatable).
0
 
LVL 34

Expert Comment

by:Sancler
ID: 18861687
Charlie

Your code looks fine.  But I've one question: why?

What you've produced is effectively a DataGrid or DataGridView with a CheckBox column and a readonly Name/Description column.  Because you don't want all the data from your datatable, some customisation of any grid would be necessary.  But I'm not sure that coding that would be any more taxing than creating your control array.  And a lot would be done for you automatically - e.g. the number of rows - and there would be the advantage (?) of databinding.

I appreciate that that may look like quibbling about the particular example you've used, rather than addressing the more basic question of whether control arrays are "a good thing".  But I do think that the answer to that basic question is more open than is sometimes assumed.  There's an awful lot of things that we were used to pre VB.NET and so which we're tempted to want to carry over.  But - with one exception, which your approach doesn't address - I'm not sure that there is anything that could be done with VB6 control arrays which cannot be done (probably as easily, once we get used to .NET ways) with VB.NET.  The exception is the design time facility of creating one control, giving it an index, and then copying it, each copy being added to the control array.

Let me stress that I am not suggesting that control arrays are "a bad thing".  But what I am suggesting is that the simple fact that we found them useful in VB6 may not, of itself, be a good enough reason for wanting to replicate them in VB.NET.  In each case, before constructing a control array in VB.NET, I would want to ask "what is it that this is going to allow me to do, or do more easily, that is not possible, or too difficult, using the facilities that are already present in VB.NET"?  And, though circumstances will alter cases and there is obviously a large element of personal choice in this, my answer would very often be "Nothing".

Roger
0
 
LVL 24

Expert Comment

by:Jeff Certain
ID: 18861863
I just noticed that my suggestion re: generics is not applicable, since that's a VB2005 feature...
0
 

Author Comment

by:charlieb01
ID: 18863027
Roger,

I appreciate your comments. My main reason for getting into this coding in the first place was that my company uses a core program (very large) for every piece of test equipment it sells. We are required to provide the source code and a copy of the development language (VB) to our clients. VB6 is becomming very difficult to purchase.
I have a software engineer who told me that she could not develop the core program we now have in VB6 into VB.NET - So this problem has been around for several years. Since it is a small company and we cannot afford to hire an outside contractor or another software engineer, I decided to dig out my old programming tools (that I have not used in many years) and attack the problem.
My first goal is to replicate the old VB6 core program as closely as possible so my software engineer will be able to easily follow it.
My next goal is to use what I am learning about VB.NET and apply that knowledge to developing a NEW core program with a fresher feel and look and something that will be easier to customize for each client.

But since you brought it up, I would be curious about how to develop a datagrid that is programmatically bound to a database table that could hold checkboxes and radio (or Option) buttons. My software engineer has had me purchase ComponentOne ActiveX products before for every project and I was told one of the reasons was that only TrueDBGrid could handle radio buttons or checkboxes. I would rather not spend the extra money if it is not necessary.

I appreciate any feedback.

Thanks,
Charlie
0
 
LVL 34

Accepted Solution

by:
Sancler earned 500 total points
ID: 18865472
Charlie

Both the DataGrid (which is the VB.NET 2003 native grid control) and the DataGridView (which is the VB.NET 2005 grid control) have a checkbox columntype built in.  You're on 2003, so try this bit of code in a form with a datagrid on it.

    Private dt As New DataTable("TestTable")

    Private Sub filltable()
        Dim dc0 As New DataColumn("ID", GetType(Integer))
        dt.Columns.Add(dc0)
        Dim dc1 As New DataColumn("Check", GetType(Boolean))
        dt.Columns.Add(dc1)
        For i As Integer = 1 To 10
            Dim dr As DataRow = dt.NewRow
            dr(0) = i
            dr(1) = (i Mod 2 = 0)
            dt.Rows.Add(dr)
        Next
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        filltable()
        DataGrid1.DataSource = dt
   End Sub

As you will see, because one of the columns in the datasource is of datatype Boolean, the datagrid automatically represents it as a checkbox.

Unfortunately, it's not quite as good as it may look at first sight, because if you click on any of the checkboxes you will see that it cycles through three states - checked, unchecked and indeterminate (grayed) - rather than just two - checked and unchecked, corresponding to true and false.  But if you're prepared to setup the datagrid with your own code, rather than just relying on the autogeneration of columns via the binding, that is easily solvable: see this link

http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c44c.aspx#q754q

Radio buttons are a bit more complicated.  I've never given any real though to it because I feel that, visually, more than a couple of radiobuttons in a grid might look odd; and two (or even three) states can be handled with a checkbox.  It looks like it can be done with a DataGridView in 2005: see this link

http://msdn2.microsoft.com/en-us/library/aa730882(VS.80).aspx

A quick Google suggests that it might be difficult in a Forms, rather than a Web, app.

One thing I would suggest is that you should try VB.NET 2005.  The Express Version is downloadable for free.  While the Express version lacks some of the bells and whistles which may be desirable in a full industrial/commercial development environment it can handle some pretty sophisticated applications even in those.  And, importantly for present purposes, the bits that were missing would not stop you trying out the development of your new core program which it sounds like you are intending to do on a single developer, rather than a team, basis.  It's DataGridView is, in my view, much easier to work with than the DataGrid.  In particular, it has an inbuilt combobox column style.  And it's that, rather than trying to develop radiobuttons, that I would use if I wanted to offer the user a restricted range of choices within a grid.

Roger
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now