Finding Controls on Forms
Posted
Mon, Jul 27 2009 10:43
by
Deborah Kurata
There are often times that you need to find specific controls on a Windows Form (WinForm). For example, you may want to find all of the TextBoxes to clear their contents, set their background color, or hook up events. You may want to find all of the checkboxes to check or uncheck them. Or find all of the buttons to hook up events or change their color.
Since a Windows Form has a Controls collection, it may seem obvious to simply loop through the Control's collection to find all of the desired controls.
But many of the controls provided in WinForms can contain other controls. Take this form for example:
This form contains two Panel controls. The top Panel control contains several Label controls and a ComboBox. The bottom Panel control contains Labels and TextBoxes.
If you look at the Controls collection for the form in this example, you find that it contains only two controls. Only the two Panel controls are actually on the form. The other controls are on the Panel controls. So to find those controls, you need to loop through the Controls collection of each Panel.
If you put a Tab control on a Panel control, then the TextBox controls would be on the Tab control which is on the Panel control. The easiest way to look for controls that could be on other controls which in turn could be on other controls, is to use recursion.
Recursion is basically calling a method from the method itself. (You can find a more detailed explanation here.) The following demonstrates recursion to find all of the TextBoxes on a form.
In C#:
private void ProcessControls(Control ctrlContainer)
{
foreach (Control ctrl in ctrlContainer.Controls)
{
if (ctrl.GetType() == typeof(TextBox))
{
// Do whatever to the TextBox
}
if (ctrl.HasChildren)
ProcessControls(ctrl);
}
}
In VB:
Private Sub ProcessControls(ByVal ctrlContainer As Control)
For Each ctrl As Control In ctrlContainer.Controls
If TypeOf ctrl Is TextBox Then
' Do whatever to the TextBox
End If
' If the control has children,
' recursively call this function
If ctrl.HasChildren Then
ProcessControls(ctrl)
End If
Next
End Sub
The code begins by processing each control within the defined container control using the container’s Controls collection. The control’s type is checked to determine if it is the desired type of control. This technique can be used to look for any type of control or multiple types of controls.
The HasChildren property of the control is checked to determine if the control itself is a container for other controls. If so, it calls this method recursively using the control as the container control.
This method resides in the Form and is called as follows.
In C#:
ProcessControls(this);
In VB:
ProcessControls(Me)
The form itself is passed into the ProcessControls method as the highest level container. If you only want to search for controls within some other container, pass it instead of the entire form. For example, if you only wanted to search for TextBox controls on Panel2 or on controls that are on Panel2, you would pass Panel2 instead of the form (this or me).
Finding Controls By Name
If you want to find a control or set of controls by name, there is an easier way.
In C#:
Control[] ctrls = this.Controls.Find("TextBox1", true);
In VB:
Dim ctrls() As Control = Me.Controls.Find("TextBox1", True)
This code uses the Find method of the controls collection. The first parameter defines the name of the control(s) to find. If the second parameter is true, the Find will search through all child controls, performing the recursive operation for you. If it is false, it will only look through the form’s Controls collection.
When I was first working with the Find method, I thought it odd that it returned an array since you can only put one control on the form named “TextBox1”. However, you can add multiple controls with the same name using Controls.Add. Also, if you build a composite user control you can also put a TextBox1 on the user control. So if you also have a TextBox1 on the form, the Find method will find two controls named “TextBox1”.
Enjoy!