Introduction
In this article, I will show you how to perform a recursive controls iteration to get all the controls inside a form.
Background
Every form has a collection of controls inside it. This collection can be accessed through this.Controls
. To retrieve them, first we are going to create a method called GetControls()
(that receives a parameter of type Control.ControlCollection
, here called a_oControlCollection
) and then use a foreach
statement to iterate through a_oControlCollection
, as shown below:
private void GetControls(Control.ControlCollection a_oControlCollection)
{
foreach(Control t_oBaseControl in a_oControlCollection)
{
}
This code works fine only if we don't have nested controls, which happens when we use containers, menus and toolbars. So, in this case, we have to iterate through each container to retrieve its controls. But, how can we know if the current control is a common control, a container, a menu or a toolbar? The best way I found is to use a switch
statement to check the control's type, as shown in the code below:
switch(t_oBaseControl.GetType().Name)
{
}
Now, we have all the control's types and we have to create a case
statement for each type that we want. For those controls that aren't a container, menu or toolbar, we can get them directly, as shown below (adding them to a ComboBox
):
case "Button":
case "CheckBox":
case "CheckedListBox":
case "ComboBox":
case "DateTimePicker":
case "Label":
case "LinkLabel":
case "ListBox":
case "ListView":
case "MaskedTextBox":
case "MonthCalendar":
case "NumericUpDown":
case "PictureBox":
case "ProgressBar":
case "RadioButton":
case "RichTextBox":
case "TextBox":
case "WebBrowser":
cbbControls.Items.Add(t_oBaseControl.Name);
break;
For the FlowLayoutPanel
, GroupBox
, Panel
and TableLayoutPanel
, we are going to add them to the ComboBox
and then recursively call the GetControls()
method using their ControlCollection
, like below:
case "FlowLayoutPanel":
case "GroupBox":
case "Panel":
case "TableLayoutPanel":
cbbControls.Items.Add(t_oBaseControl.Name);
GetControls(t_oBaseControl.Controls);
break;
For the SplitContainer
, we're going to do the same for each panel.
case "SplitContainer":
cbbControls.Items.Add(t_oBaseControl.Name);
GetControls(((SplitContainer)t_oBaseControl).Panel1.Controls);
GetControls(((SplitContainer)t_oBaseControl).Panel2.Controls);
break;
And the same for the TabControl
, for each TabPage
.
case "TabControl":
cbbControls.Items.Add(t_oBaseControl.Name);
foreach(TabPage t_oTabPage in ((TabControl)t_oBaseControl).TabPages)
{
cbbControls.Items.Add(t_oTabPage.Name);
GetControls(t_oTabPage.Controls);
}
break;
For the *Strip components, things become annoying. For the MenuStrip
, we're going to first iterate through all ToolStripItem
s and, for each ToolStripMenuItem
, call another method called GetMenuItems()
(that receives a ToolStripItemCollection
), and pass as parameter the DropDownItems
property. See below:
case "MenuStrip":
cbbControls.Items.Add(t_oBaseControl.Name);
foreach(ToolStripMenuItem t_oMenuItem in ((ToolStrip)t_oBaseControl).Items)
{
cbbControls.Items.Add(t_oMenuItem.Name);
GetMenuItems(t_oMenuItem.DropDownItems);
}
break;
For the StatusStrip
and ToolStrip
, we're going to first use a for
statement to iterate through all ToolStripItem
s. After that, we're going to use a switch
statement to check its type. For the ToolStripButton
, ToolStripComboBox
, ToolStripLabel
, ToolStripMenuItem
, ToolStripProgressBar
, ToolStripStatusLabel
and ToolStripTextBox
, we can cast them all to ToolStripItem
. But for ToolStripSplitButton
and ToolStripDropDownButton
, we need to cast to their exact type and then call GetMenuItem()
passing their DropDownItems
as parameter to retrieve the controls nested, as shown below:
case "StatusStrip":
case "ToolStrip":
cbbControls.Items.Add(t_oBaseControl.Name);
for(int i = 0;i < ((ToolStrip)t_oBaseControl).Items.Count;i++)
{
switch(((ToolStrip)t_oBaseControl).Items[i].GetType().Name)
{
case "ToolStripButton":
case "ToolStripComboBox":
case "ToolStripLabel":
case "ToolStripMenuItem":
case "ToolStripProgressBar":
case "ToolStripStatusLabel":
case "ToolStripTextBox":
ToolStripItem t_oToolStripItem =
(ToolStripItem)((ToolStrip)t_oBaseControl).Items[i];
cbbControls.Items.Add(t_oToolStripItem.Name);
break;
case "ToolStripSplitButton":
ToolStripSplitButton t_oToolStripSplitButton =
(ToolStripSplitButton)((ToolStrip)t_oBaseControl).Items[i];
cbbControls.Items.Add(t_oToolStripSplitButton.Name);
GetMenuItems(t_oToolStripSplitButton.DropDownItems);
break;
case "ToolStripDropDownButton":
ToolStripDropDownButton t_oToolStripDropDownButton =
(ToolStripDropDownButton)((ToolStrip)t_oBaseControl).Items[i];
cbbControls.Items.Add(t_oToolStripDropDownButton.Name);
GetMenuItems(t_oToolStripDropDownButton.DropDownItems);
break;
}
}
break;
Just for example, we can also iterate through all nodes inside a TreeView
. Inside a foreach
statement, we call method GetNodes()
passing as parameter the current TreeNode
's Nodes
property.
case "TreeView":
cbbControls.Items.Add(t_oBaseControl.Name);
foreach(TreeNode t_oTreeNode in ((TreeView)t_oBaseControl).Nodes)
{
cbbControls.Items.Add(t_oTreeNode.Name);
GetNodes(t_oTreeNode.Nodes);
}
break;
Below are those two necessary methods mentioned earlier:
private void GetMenuItems(ToolStripItemCollection a_oToolStripItemCollection)
{
foreach(ToolStripItem t_oToolStripItem in a_oToolStripItemCollection)
{
cbbControls.Items.Add(t_oToolStripItem.Name);
switch(t_oToolStripItem.GetType().Name)
{
case "ToolStripMenuItem":
GetMenuItems(((ToolStripMenuItem)t_oToolStripItem).DropDownItems);
break;
}
}
}
private void GetNodes(TreeNodeCollection a_oTreeNodeCollection)
{
foreach(TreeNode t_oTreeNode in a_oTreeNodeCollection)
{
cbbControls.Items.Add(t_oTreeNode.Name);
GetNodes(t_oTreeNode.Nodes);
}
}
Using the Code
To use this code, simply call GetControls()
inside a form passing this.Controls
as a parameter. That's all! As simple as that. I made most of the possible case
statements, but a few still have to be implemented. I'll leave this as an exercise for you. Any questions? Let me know!
History
- April 2008 - First published
Copyright © 2007 Sergio A. B. Petrovcic. All rights reserved. Do not publish to other sites without my express permission. Link to this article in accordance with this site's policies and procedures.