Forms also have a collection of controls (Controls property) that you can loop through. This is useful for when you want to do something to multiple controls and don’t want to have to manually type out code to deal with individual controls.
Here’s an example of looping through a form’s top-level controls:
foreach(Control control in this.Controls)
{
control.Visible = true;
}
Code language: C# (cs)
Note: In the foreach, use ‘Control’ instead of ‘var’ for the loop variable.
In this article, I’ll show how to loop through controls of a specific type (ex: TextBox), and how to loop through control containers – such as a TabControl.
Table of Contents
Loop through controls of a specific type
All controls derive from the Control class. If you want to do something based on the specific control type (like TextBox), you can either 1) Loop through the controls and check the type, or 2) Filter the control collection for a specific type. I’ll show examples of both options below.
Option 1 – Check the control type
A good, flexible way to check for a specific control type is to use the is operator in the loop. Here’s an example of only changing a control property if it’s a TextBox:
foreach (Control control in this.Controls)
{
if (control is TextBox)
{
control.Visible = true;
}
}
Code language: C# (cs)
If you need to check for multiple control types, the simplest way is to use a switch with the type pattern:
foreach(Control control in this.Controls)
{
switch(control)
{
case TextBox txtBox:
//do something with the TextBox
txtBox.Text = "Hi";
break;
case ComboBox comboBox:
//do something with the ComboBox
comboBox.SelectedIndex = 0;
break;
}
}
Code language: C# (cs)
Note: This really beats having to type out a big if-elseif statement and using the is operator repeatedly.
Option 2 – Use the OfType() filtering method
An alternative to checking the control type is to use the OfType() filtering method. This returns all controls of a specified type from a control collection. Here’s an example of getting all of the form’s top-level TextBox controls:
foreach(var txtBox in this.Controls.OfType<TextBox>())
{
//do something with TextBox
txtBox.Text = "Hi";
}
Code language: C# (cs)
This is nice and simple if you only need to look at one level of controls.
Loop through control containers
Controls can contain zero or more child controls. When you loop through Form.Controls, you’re really only looking at the form’s top-level controls. If your form has control containers (such as TabControl, SplitContainer, GroupBox, etc…), you can either 1) Loop through the top-level controls and recursively loop through the control containers or 2) Directly loop through specific control containers.
Recursively loop through all of the form’s controls
Forms contain a control hierarchy – a tree – and recursion is the natural choice for traversing a tree. You can check if a control is really a control container by checking the HasChildren property and then recursing over its child controls. Here’s an example of recursively looking for all TextBox controls:
private void btnSetTextBoxesToHi_Click(object sender, EventArgs e)
{
Loop(this.Controls);
}
private void Loop(Control.ControlCollection controls)
{
foreach(Control control in controls)
{
if (control.HasChildren)
{
//Recursively loop through the child controls
Loop(control.Controls);
}
else
{
if (control is TextBox txtBox)
{
//do something with the TextBox
txtBox.Text = "Hi";
}
}
}
}
Code language: C# (cs)
Note: This passes the collection of child controls and only recurses if a control has child controls. This minimizes the number of recursive calls and goes to exactly the right depth. Compare this with the inefficient approach of unconditionally recursing on every control object, which maximizes the number of recursive calls and always goes one level deeper than it needs to.
Here’s what this looks like in the UI after you click the button. Notice that it updated all TextBox controls (top-level and those contained in a TabControl):
Directly loop through a control container
Using recursion is a good option if you want to look at ALL controls, or if you are making general-purpose code that can potentially be used for all forms. Don’t use the recursive approach unless you really need to. If you have a form that has a control container, you can directly loop through its controls instead. Here’s an example:
foreach(TabPage tabPage in tabs.TabPages)
{
foreach(var txtBox in tabPage.Controls.OfType<TextBox>())
{
//do something with the TextBox in the tab page
txtBox.Text = "Hi";
}
}
Code language: C# (cs)
Keep your code simple and direct when possible.
“Note: In the foreach, use ‘Control’ instead of ‘var’ for the loop variable.”
OMG! Thank you!
You’re welcome! I’m glad that little note helped someone.