65.9K
CodeProject 正在变化。 阅读更多。
Home

控件迭代

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.35/5 (9投票s)

2008年5月5日

CPOL

3分钟阅读

viewsIcon

48243

downloadIcon

831

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

ControlsBinary

引言

在本文中,我将向您展示如何执行递归控件迭代以获取窗体内的所有控件。

背景

每个窗体都有一个控件集合。 可以通过 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;

对于 FlowLayoutPanelGroupBoxPanelTableLayoutPanel,我们将它们添加到 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;

对于 StatusStripToolStrip,我们将首先使用 for 语句遍历所有 ToolStripItem。 之后,我们将使用 switch 语句来检查其类型。 对于 ToolStripButtonToolStripComboBoxToolStripLabelToolStripMenuItemToolStripProgressBarToolStripStatusLabelToolStripTextBox,我们可以将它们全部转换为 ToolStripItem。 但是对于 ToolStripSplitButtonToolStripDropDownButton,我们需要转换为它们的精确类型,然后调用 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() 将当前 TreeNodeNodes 属性作为参数传递。

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。 版权所有。 未经我明确许可,请勿发布到其他网站。 请按照本网站的政策和程序链接到本文。

© . All rights reserved.