|
Introduction
Any VB programmer who has moved to VB.NET knows the frustration of losing the ability to create control arrays in a form. VB.NET adds a great amount of flexibility and power, but at the cost of losing some of the features that made VB a great rapid development environment that hid many of the programming details from the developer. One such loss is the control arrays. In the past, you could drop a number of controls on the screen with the same name, and VB took care of creating a member variable for you, so that you could reference the controls as an array within your code. VB.NET has not done this for you yet.
Here is a very simple solution that links the controls on the form to a member variable in your code, which gives you the closest thing to a VB control array, using one function call. The only constraint is that you must follow a naming convention for your controls. NameXXX where 'Name' is any string name you would like for this group of controls and XXX is an integer value representing the index of the array it is to be assigned to.
For example, if you have five TextBoxes on the screen, you would name them as follows: myTextBox0
myTextBox1
myTextBox2
myTextBox3
myTextBox4
The function included in the sample project will then search the form for myTextBoxXXX, strip off the index and assign it to a control array for you. A sample call to create the control array is as follows: Dim textBoxes As TextBox() = _
ControlArrayUtils.getControlArray(Me, "myTextBox")
That's it. You can then use TextBoxes in your code to do whatever you need. Dim mTextBoxes() As TextBox
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
mTextBoxes = ControlArrayUtils.getControlArray(Me, "TextBox")
mTextBoxes(1).Text = "Form Load Test 1"
end sub
Dim mTextBoxes() as TextBox
Private Sub Form1_Load(ByVal sender as System.Object, _
ByVal e as System.EventArgs) Handles MyBase.Load
Dim ii as integer
myTextBoxes = ControlArrayUtils.getControlArray(Me."TextBox")
for ii=1 to 5
myTextBoxes(ii).Text = ii
next ii
end sub
You can also declare the TextBoxes array as a member variable of your form, and then call this function once in the Form_Load event. The array will then be ready for use anywhere on the form after that, giving almost identical functionality as the VB6 method. The current implementation looks only for controls on the Form. But it is possible to do a recursive search or a search on a specific control. This will come later.
The ControlArrayUtils code is listed below and is downloadable as a demo: Public Class ControlArrayUtils
Public Shared Function getControlArray(_
ByVal frm As Windows.Forms.Form, _
ByVal controlName As String, _
Optional ByVal separator As String = "") As System.Array
Dim i As Short
Dim startOfIndex As Short
Dim alist As New ArrayList
Dim controlType As System.Type
Dim ctl As System.Windows.Forms.Control
Dim ctrls() As System.Windows.Forms.Control
Dim strSuffix As String
Dim maxIndex As Short = -1
For Each ctl In frm.Controls
startOfIndex = ctl.Name.ToLower.IndexOf(_
controlName.ToLower & separator)
If startOfIndex = 0 Then
strSuffix = ctl.Name.Substring(controlName.Length)
If IsInteger(strSuffix) Then
If Val(strSuffix) > maxIndex Then _
maxIndex = Val(strSuffix)
End If
End If
Next ctl
If maxIndex > -1 Then
For i = 0 To maxIndex
Dim aControl As Control = _
getControlFromName(frm, controlName, i, separator)
If Not (aControl Is Nothing) Then
controlType = aControl.GetType
End If
alist.Add(aControl)
Next
End If
Return alist.ToArray(controlType)
End Function
Public Shared Function getMixedControlArray(_
ByVal frm As Windows.Forms.Form, ByVal controlName As String, _
Optional ByVal separator As String = "") As Control()
Dim i As Short
Dim startOfIndex As Short
Dim alist As New ArrayList
Dim controlType As System.Type
Dim ctl As System.Windows.Forms.Control
Dim ctrls() As System.Windows.Forms.Control
Dim strSuffix As String
Dim maxIndex As Short = -1
For Each ctl In frm.Controls
startOfIndex = ctl.Name.ToLower.IndexOf(_
controlName.ToLower & separator)
If startOfIndex = 0 Then
strSuffix = ctl.Name.Substring(controlName.Length)
If IsInteger(strSuffix) Then
If Val(strSuffix) > maxIndex Then _
maxIndex = Val(strSuffix)
End If
End If
Next ctl
If maxIndex > -1 Then
For i = 0 To maxIndex
Dim aControl As Control = getControlFromName(frm, _
controlName, i, separator)
alist.Add(aControl)
Next
End If
Return alist.ToArray(GetType(Control))
End Function
Private Shared Function getControlFromName(_
ByRef frm As Windows.Forms.Form, _
ByVal controlName As String, ByVal index As Short, _
ByVal separator As String) As System.Windows.Forms.Control
controlName = controlName & separator & index
For Each ctl As Control In frm.Controls
If String.Compare(ctl.Name, controlName, True) = 0 Then
Return ctl
End If
Next ctl
Return Nothing
End Function
Private Shared Function IsInteger(ByVal Value As String) As Boolean
If Value = "" Then Return False
For Each chr As Char In Value
If Not Char.IsDigit(chr) Then
Return False
End If
Next
Return True
End Function
End Class
| You must Sign In to use this message board. |
|
| | Msgs 1 to 16 of 16 (Total in Forum: 16) (Refresh) | FirstPrevNext |
|
 |
|
|
But, I'm gradually learning to live without them. I realize this article is dated, but I just wanted to say that, after learning some C# and playing with .NET in general, I realized that control arrays are something that can be implemented in a number of ways with any .NET language I've seen. It's a little cumbersome at times, but you can actually write little wrapper classes to make things seem more transparent. Sure, it's not the best approach all of the time, but it works if you need it. I also don't mind tying multiple controls to one event, as long as I can distinguish between them in code. Fact is, with OOP like it is today, I can't imagine that the VB.NET team at Microsoft will ever bother with another control array implementation like VB6 has, I guess it's possible though. After the revisions so far and all the work they have put into getting us OO, if they had any plans to implement the feature, don't you think they would have by now? I do!
Gary W. Morris, Entepreneur
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This works nice with buttons, but cant get it to work with ovalshapes from microsofts power pack. Can anyone help
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Found this and wasn't sure why it was unused.
"Dim ctrls() As System.Windows.Forms.Control"
I deleted both of them and it didn't seem to effect the program.
Also if you are trying to use this in VS2005 with Option Strict and Explicit On (maybe needs it even if you don't have it on) you have to specify the imports
Imports System Imports System.Collections Imports System.Windows.Forms Imports Microsoft.VisualBasic.Conversion ' Or the Val doesn't work. Headache to figure out why too!
Also in the use of it Ctype is required.
Dim textBoxes As TextBox() = CType(ControlArrayUtils.getControlArray(Me, "TextBox"), TextBox())
Took me awhile to realize it needed () after it was cast as a textbox.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have updated the sample application to support recursive search of all controls on the forms. The older version would only look for controls directly on the form, it would not see controls that are on a panel, groupbox, or other controls. This version will find all the controls, regardless of their parent control.
-- modified at 18:41 Monday 21st May, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Dear kepler77:
I have been using other aproaches to resolve the lack of Control Arrays in VB.NET. Yours is the better one I found for the second of the following Control Arrays issues:
1. Reusing events. 2. Accessing properties through a simple "control_name(index)" naming convention.
There is a third issue that remains to be solved and I sincerely hope that Lie1296 is right when he says that future versions of VB.NET will have Control Arrays included:
3. Not having to worry about this, since Control Arrays in VB should be taken for granted.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Get over it my friend, the VB6 days are well over.
If there's no control array in .NET, it's just because there are better ways to do things now.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
i agree, control arrays were just a way of getting around obvious deficiencies in vb6 - that you couldn't reuse event handlers, and that dynamic control creation was... difficult. Also the "too many controls on this form" thing, which you could get round by using control arrays. There are better ways to do things in vb.net, and its probably pointless trying to recreate this vb6 "feature"
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
OK, I should tell you that Control Array in VB6 is one of the greatest strength in VB. And obviously enough, it is NOT a way to get round VB6 "deficiencies" as you say it. Of course you can reuse event handlers in VB.NET, but what for?
Other than what have been mentioned, we use Control Arrays for ORGANIZING PURPOSE, to group multiple related controls, easily, and control arrays helps us to make sure we don't reserve too many control names. (see: And for article creator, you might want to see MS's implementation of rec http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchcreatingcontrolarraysinvisualbasicnetvisualcnet.asp for MS's official substitute of Control Array in VB.NET and C#)
If you reuse events in VB.NET, you're not grouping the control. And dynamic control creation wasn't difficult in VB6, it's almost as easy to dynamically create control in VB6 as it is on VB.NET.
And FYI, there are indications that future VB.NET might have Control Arrays back. This is the indication that Control Array was and is still a good idea.
|
| Sign In·View Thread·PermaLink | 5.00/5 (3 votes) |
|
|
|
 |
|
|
"And FYI, there are indications that future VB.NET might have Control Arrays back. This is the indication that Control Array was and is still a good idea."
1. create an array of type 'control' 2. create the buttons (or wheteren controlytype) in the code 3. assign the events 4. add the newly created control to the array
Control arrays were a "solution" for one of the many limitations of VB. The thing is VB 'programmers' got used to this "solution" and can't let go of it, but please let go of it. There are more generic solutions now. Use those.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
So, can this be done without using the vb6."controls arrays" object?
IE:
Me.cmd = New Microsoft.VisualBasic.Compatibility.VB6.ButtonArray(Me.components) Me.label = New Microsoft.VisualBasic.Compatibility.VB6.LabelArray(Me.components)
For in .NET, we want to stay away from VB6 loadings. I am not sure how you create an array of commands in .NET and simply show them on the screen? This does not work...
Dim i As Int16 Dim aButton(10) As Button For i = 0 To 9 aButton(i) = New Button aButton(i).Left = 0 aButton(i).Height = 50 aButton(i).Width = 50 aButton(i).Top = aButton(i).Height * i + 50 aButton(i).Visible = True aButton(i).Text = "hello " & i Next
HAK
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Yes, it can be done. I made an example where 10 buttons are created dynamicly and, when any of them are clicked the text will shown on it and buttons next to it.
Dim buttons As New List(Of Button)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim i As Byte Dim aButton As Button
For i = 0 To 9 aButton = New Button With aButton .Parent = Me .Left = 0 .Height = 50 .Width = 50 .Top = .Height * i + 50 .Visible = True .Tag = i .Name = "button_" & i AddHandler .Click, AddressOf button_Click End With
buttons.Add(aButton) Next End Sub Private Sub button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'clear previous results buttons.ForEach(New Action(Of Button)(AddressOf clear_text))
'add results Dim arv As Byte = CByte(sender.tag) sender.text = CStr(arv) If arv > 0 Then buttons(arv - 1).Text = "next >" If arv < buttons.Count - 1 Then buttons(arv + 1).Text = "< pre" End Sub Sub clear_text(ByVal element As Button) element.Text = "" End Sub
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Control arrays might be a solution for limitations vb have had in the past, but the important thing is, the concept of simple managment of multiple identical controls as an array is a good idea. We doesn't really need to care how control array was or is implemented, as long as it works in such a way that allows us to manage multiple controls as an array easily without hassle.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
My dear friend, the fact that you don't need Control Arrays does't mean that nobody else has a good use for them.
In the type of applications I use to develop I find Control Arrays very useful since they allow me to achieve two main objectives: 1. Develop in a RAD way. 2. Use "smart" code in very few lines to perform repetitive tasks.
And you say that there are better ways to do things now... well may be there are other ways. IMHO, which one is better depends on who is the developer and what kind of application he is developing.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Carl: OK, lets put the rubber to the road. If there is a more eloquent, ease of implementing, straight forward, non-confusing, simplistic way of implementing array controls in VB.NET -- show me.
Thanks, HAK
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It is a rhetorical request(with answer - no?). You want a better way to do - Object(Index).parameter=value, where Object(Index) is what get's the individual object?
My way, would be to ignore the word "simplistic" and say "Yes, there is". Rather then using array(sequential blocks of memory, where block size is been set by the type, and index sets directly with what block of memory we want to handle) use list(blocks of memory, where block size is been set by the type, and index sets indirectly with what block of memory we want to handle).
Lists are declared like: Dim a As List(Of Button)
Note that elements can have names of "whatever" and you can add and eliminate controls without having to deal all other controls in list. One can still use Object(Index).parameter=value, just access to the block of memory is different.
I allso like to note that vb.net supports Delegate(sender,expression) where sender is what get's the individual object. So I think, this enables to depreciate need of arrays or lists in many cases(and it is simplistic).
I hope you got your wanted answer,
Margus
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|