Upgrading the Controls Collection

To add and remove controls at run time, Visual Basic 6.0 provides the Controls collection. The Controls collection is a dynamic collection of controls on a form or container. Through this collection, it is possible to add and remove controls on a form (or container) at run time.

For example, consider the following code that adds a Label dynamically to a form at run time.

Dim labelControl As Control

Set labelControl = Me.Controls.Add("VB.Label", "labelControl") labelControl.Visible = True

This code adds a Label to the form and makes it visible. It is also easy in Visual Basic 6.0 to dynamically remove a control. The following line of code removes the Label that was added in the preceding code example.

Me.Controls.Remove "labelControl"

One of the major disadvantages of the Visual Basic 6.0 model is that the Controls collection does not support Microsoft IntelliSense® technology. You have to remember the methods, parameters, and ProgID of the control to add.

The upgrade wizard does not automatically upgrade Visual Basic 6.0 code using the Controls collection Add method because of changes in the behavior of Add between Visual Basic 6.0 and Visual Basic .NET. Fortunately, Visual Basic .NET does provide an alternative to achieve the same functionality. It is relatively easy to add and remove intrinsic controls in Visual Basic .NET. The following example demonstrates how to dynamically add a Label to a form at run time in Visual Basic .NET.

Dim c As Control c = New Label() c.Name = "labelControl" Me.Controls.Add(c)

In Windows Forms, the form model used in Visual Basic .NET, controls are indexed by number instead of name. To remove a control by name, you have to iterate through the Me.Controls collection, find the desired control, and remove it. The following code shows how to remove the newly added control by name in Visual Basic .NET.

Dim tempControl As Control

For Each tempControl In Me.Controls

If tempControl.Name = "labelControl" Then Me.Controls.Remove(tempControl) Exit For End If Next

For Visual Basic 2005:

In the new Visual Basic 2005, the Controls collection will provide methods that allow removing controls in the same manner as Visual Basic 6.0, so you will not have to iterate through the Controls collection. For example, it will be possible to replace the preceding iteration example with a single line of code.

Me.Controls.RemoveByKey(tempControl)

The Item indexed property allows the user to access one control in the collection by specifying the numeric index of the control. In Visual Basic 2005, it is also possible to access one control by indicating the name of the control (as a string).

Visual Studio 2005 also adds other new methods to the ControlCollection class that help achieve some of the functionality that Visual Basic 6.0 programmers expected from the ControlArray. ControlCollection is the type of the Controls property of the Control class. This class now contains a find() method that allows you to search a control and all its child controls recursively for a control with a specific name and returns an array with all the matching controls. The other new methods are RemoveByKey(), ContainsKey(), IndexOfKey(), and a new string parameter for the Item property. All these new methods provide ways to manipulate the ControlCollection using the names of the controls instead of their index. For more information, see "Control.ControlCollection Class (System.Windows.Forms)" in the .NET Framework Class Library on MSDN.

For more information about the new Controls collection available in Visual Basic 2005, see "Controls Collection for Visual Basic 6.0 Users" in Visual Basic Concepts on MSDN. Please note that at the time of this writing, the content contained in this documentation refers to a pre-release version of Visual Basic 2005 and is subject to change.

Dynamically adding ActiveX controls at run time requires a bit more work. Visual Basic .NET creates wrappers for ActiveX controls. These wrappers must exist before a control can be added. In addition, most ActiveX controls have design-time licenses that must be present before the control can be created on the form. Visual Basic .NET compiles the license into the executable. These factors mean that the control must already be present in the project before it can be dynamically added at run time. One way to do this is to add a dummy form to the project and put all ActiveX controls that will be dynamically added to this form. After you create this dummy form, you can dynamically add the ActiveX control to any form in your project. The following code shows how to dynamically add a Windows Common Controls TreeView control to a form (assuming the project already has a dummy form with a TreeView added).

Dim activexControl As New AxMSComctlLib.AxTreeView() activexControl.Name = "TreeViewUsuers" Me.Controls.Add(activexControl)

After the control is added, it can be dynamically removed in a manner similar to removing an intrinsic control. Only adding requires additional work.

It is important to consider that there is a behavior difference between the Visual Basic 6.0 and Visual Basic .NET Controls collection. In Visual Basic 6.0, this collection contains all the controls that have been added to a particular Form, including controls that were added to other container controls such as PictureBox or Frame controls. In Visual Basic .NET, the Controls collection includes only the controls that were directly added to the control that owns the collection; for example, if a Form contains a Panel control that contains a Button control named button1, button1 will not be contained in the Controls collection that belongs to the Form; instead of that, button1 will be contained in the panel's Controls collection. As a consequence, iterating through the elements in a form's Controls collection will not consider all the controls contained in the form, as it did in Visual Basic 6.0. For more information about the Controls collection behavior differences, see "Getting Back Your Visual Basic 6.0 Goodies" on MSDN.

The following code example presents a typical For Each loop that will perform an operation on all the controls in a Visual Basic 6.0 form.

Function ListOfControlNames() As String

Dim res As String

For Each c In Me.Controls res = res & c.Name & " "

Next

ListOfControlNames = res End Function

If the form has the layout illustrated in Figure 7.1, the output of the previous function will be "Framel Commandl."

Pl[jnrm1

EBB

r ,

■ Commandl ■

■ ■ ■

Form with nested controls

Figure 7.1

Form with nested controls

After the ListOfControlNames function is upgraded, the following code will be the result.

Function ListOfContro1Names() As String Dim c As System.Windows.Forms.Control Dim res As String For Each c In Me.Controls res = res & c.Name & " " Next c

ListOfControlNames = res End Function

In Visual Basic .NET, the output of the function will be "Framel." There is a clear difference with the result obtained in Visual Basic 6.0. Correcting this difference would require the definition of two new functions that recursively obtain the controls contained in Forml. The two new functions are shown here.

Function MyContro1s() As ArrayList Dim res As New ArrayList GetA11Contro1s(Me, res) Return res End Function

Function GetA11Contro1s(ByVa1 c As Control, ByVal res As ArrayList) Dim curControl As Control For Each curControl In c.Controls res.Add(curControl) GetAllControlsCcurControl, res)

Next End Function

The For Each loop in the ListOfControlNames function must be changed to use the MyControls function instead of Me.Controls. It is important to notice that the order in which the controls are processed may change because of the recursive way in which the controls are obtained, if your code depends on the order in which the controls are obtained, it will require adjustments to be functionally equivalent to the Visual Basic 6.0 code.

0 0

Post a comment