在 Windows 表单中循环访问用户控件时出现问题

Issue while iterating through User Controls in a Windows Form

我在 运行 通过我的 Windows 表单中的所有用户控件时遇到问题。

我正在创建具有以下功能的 Windows 表单:

  1. 主窗体中嵌入了 3 个用户控件
  2. 主窗体也有一个组合框。在组合框中选择特定值会将相应的用户控件置于最前面。
  3. 每个用户控件都有两个复选框和两个组合框。
  4. 用户可以通过主窗体的组合框调用每个用户控件并选中复选框and/or修改每个用户控件内的组合框
  5. 完成此操作后,将有一个按钮,按下该按钮将执行以下代码。这段代码应该检查每个用户控件选中了哪些复选框,并执行一些功能:
private void button1_Click(object sender, EventArgs e)
        {
            foreach (Control c in this.Controls)
            {
                if (c is UserControl)
                {
                    foreach (Control ctl in c.Controls)
                    {

                        if (ctl is CheckBox && (ctl as CheckBox).Checked)
                        {
                            Indicator.Text = "It's in";
                        }
                    }
                }
            }
            //Some other code after this
         }

在这里,我包含了一个名为 "Indicator" 的文本框,它显示编译器是否已进入特定的 "for" 循环或 "if" 块。我观察到最里面的 "if" 没有被执行。

有人能指出为什么会这样吗?

你需要一个递归算法,

void ProcessControls(Control ctrlContainer) 
{ 
    foreach (Control ctrl in ctrlContainer.Controls) 
    { 
        if (ctrl is CheckBox && (ctrl as CheckBox).Checked)
        {
             Indicator.Text = "It's in";
        }
        if (ctrl.HasChildren) 
            ProcessControls(ctrl); 
    } 
}

我认为您最好向您的用户控件添加一些功能,这样它就可以描述其自身复选框的状态,而不是深入其中以找到它并执行逻辑。通常在 OO 编程中,当我们将事物封装在 class 中时,我们还提供通用访问器 "visible to the outside" 来描述事务的内部状态,而不是让外部代码兴趣在 class 找出他们想要什么

在某个时间点,您已将这些用户控件直接在设计器中或以编程方式添加到窗体中。在第一种情况下,他们将有自己的名字:

var u1 = usercontrol1.GetCheckboxStateArray();
var u2 = usercontrol2.GetCheckboxStateArray();

等等

或者您可能以编程方式添加它们,在这种情况下,在添加它们时在列表中跟踪它们是有意义的:

protected List<UserControl> _ucList = new List<UserControl>();
...
foreach(var result in somedatabasequery){
  var uc = new UserControl(result.Whatever);
  this.Controls.Add(uc);
  _ucList.Add(uc);
}

然后可以迭代这个列表。当然你可以争辩 "well .Controls is a collection too, so why add them to another list when they're already in an accessible collection" - 因为你在这里的原因; .Controls 是对表单上所有控件的层次结构的通用描述,它包含我们不想要的东西并且很难迭代。此列表纯粹而简单地包含了我们感兴趣的所有内容

顺便说一句,您所描述的 UI 是非典型的。在选择包含一些文本的内容下隐藏和显示控件的更常用方法是 TabControl。如果您坚持使用此 "search for UserControls in a collection of controls" 方法,则循环也可能更容易 - tabcontrols 有 tabpages,tabpages 可能有一个仅包含您的 UserControl 的 .Controls。 tabpage 本质上负责在单击页面时显示和隐藏控件,这可以简化您的代码

感谢大家的回答。碰巧的是,这个问题就在我眼皮子底下隐藏在众目睽睽之下。在每个用户控件中,我都将复选框和组合框 放在组框 中。我完全忘记了它,以至于我什至没有在我的问题中提到它们。

因此,正如@Caius 在评论中所建议的那样,代码无法运行,因为我没有处理包含这些控件的组框容器。删除组框(仅用于美观目的)后,代码开始正常运行。