控件迭代
此示例显示了如何在窗体中执行递归控件迭代

引言
在本文中,我将向您展示如何执行递归控件迭代以获取窗体内的所有控件。
背景
每个窗体都有一个控件集合。 可以通过 this.Controls
访问此集合。 要检索它们,我们首先要创建一个名为 GetControls()
的方法(该方法接收一个 Control.ControlCollection
类型的参数,这里称为 a_oControlCollection
),然后使用 foreach
语句遍历 a_oControlCollection
,如下所示
private void GetControls(Control.ControlCollection a_oControlCollection)
{
foreach(Control t_oBaseControl in a_oControlCollection)
{
}
仅当我们没有嵌套控件时,此代码才能正常工作,当我们使用容器、菜单和工具栏时就会发生这种情况。 因此,在这种情况下,我们必须遍历每个容器以检索其控件。 但是,我们如何知道当前控件是普通控件、容器、菜单还是工具栏? 我发现最好的方法是使用 switch
语句来检查控件的类型,如下面的代码所示
switch(t_oBaseControl.GetType().Name)
{
}
现在,我们拥有了所有控件的类型,并且必须为我们想要的每种类型创建一个 case
语句。 对于那些不是容器、菜单或工具栏的控件,我们可以直接获取它们,如下所示(将它们添加到 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;
对于 FlowLayoutPanel
、GroupBox
、Panel
和 TableLayoutPanel
,我们将它们添加到 ComboBox
,然后使用它们的 ControlCollection
递归调用 GetControls()
方法,如下所示
case "FlowLayoutPanel":
case "GroupBox":
case "Panel":
case "TableLayoutPanel":
cbbControls.Items.Add(t_oBaseControl.Name);
GetControls(t_oBaseControl.Controls);
break;
对于 SplitContainer
,我们将对每个面板执行相同的操作。
case "SplitContainer":
cbbControls.Items.Add(t_oBaseControl.Name);
GetControls(((SplitContainer)t_oBaseControl).Panel1.Controls);
GetControls(((SplitContainer)t_oBaseControl).Panel2.Controls);
break;
对于 TabControl
,对每个 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;
对于 *Strip 组件,事情变得很麻烦。 对于 MenuStrip
,我们将首先遍历所有 ToolStripItem
,对于每个 ToolStripMenuItem
,调用另一个名为 GetMenuItems()
的方法(该方法接收一个 ToolStripItemCollection
),并将 DropDownItems
属性作为参数传递。 见下文
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;
对于 StatusStrip
和 ToolStrip
,我们将首先使用 for
语句遍历所有 ToolStripItem
。 之后,我们将使用 switch
语句来检查其类型。 对于 ToolStripButton
、ToolStripComboBox
、ToolStripLabel
、ToolStripMenuItem
、ToolStripProgressBar
、ToolStripStatusLabel
和 ToolStripTextBox
,我们可以将它们全部转换为 ToolStripItem
。 但是对于 ToolStripSplitButton
和 ToolStripDropDownButton
,我们需要转换为它们的精确类型,然后调用 GetMenuItem()
传递它们的 DropDownItems
作为参数来检索嵌套的控件,如下所示
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;
仅作为示例,我们还可以遍历 TreeView
内的所有节点。 在 foreach
语句中,我们调用方法 GetNodes()
将当前 TreeNode
的 Nodes
属性作为参数传递。
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;
以下是前面提到的两种必要方法
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
要使用此代码,只需在一个窗体中调用 GetControls()
并将 this.Controls
作为参数传递即可。 就是这样! 就这么简单。 我编写了大部分可能的 case
语句,但还有一些需要实现。 我将把它作为给你的练习。 有什么问题吗? 告诉我!
历史
- 2008 年 4 月 - 首次发布
版权所有 © 2007 Sergio A. B. Petrovcic。 版权所有。 未经我明确许可,请勿发布到其他网站。 请按照本网站的政策和程序链接到本文。