后续行动:寻找控制之子

时间:2011-04-26 22:19:16

标签: c# forms foreach controls

我认为正确的术语是递归。我有一个Windows窗体,里面有一个标签控件,标签控件里面有四个标签,每个标签里面有多个控件 - 按钮,文本框等我想把每个按钮的光标更改为打字。

以下是我到目前为止的调查结果:

foreach (Control c in tabControl1.Controls)
         {

             // The only controls that will be found here are the tabs themselves. So, now I must run a *foreach* loop through every tab found, and look if buttons are present.

         }

评论区域在某种程度上解释了我的问题。我找到了一个在表单上反复查找控件的例子,但我不确定为什么我需要将控制名称作为参数传递,因为我试图找到每个类型按钮的控件。

以下是我在网上找到的代码: http://www.dreamincode.net/code/snippet1663.htm

再次感谢你。我喜欢听到你们所有人的意见,因为这对我来说是一次极好的学习经历。

非常感谢你的时间。

2 个答案:

答案 0 :(得分:1)

private void FindAll(Control myControl)
{
    if (myControl is Button)
        doStuff();

    foreach (Control myChild in myControl.Controls)            
        FindAll(myChild);

}

我相信这会奏效。当你第一次打电话时,你会传递表格。表单不是按钮,但它会有孩子。它拥有的每个孩子都将被传递到FindAll()。如果该控件是一个按钮,它将调用doStuff()(您可以在那里设置光标)。同样,如果该控件有任何子节点,它们将被传入。

你是对的,这个词是recurisve(一般来说,任何自称的函数或子)。因此,在此示例中,FindAll()将在某种情况下调用FindAll()。

此外,这只是示例代码;您可能需要根据应用程序的性质检查空引用。

编辑:就像你不熟悉递归一样,我很容易得到可怕的StackOverflow异常。当你最终进入一个永不停止的自我调用循环时,你将耗尽堆栈空间并看到StackOverflow异常。因此,名称www.StackOverflow.com

在这种情况下,我们不必担心因为.NET阻止我们添加创建循环引用的控件。例如 - 此代码将失败:

    GroupBox g1 = new GroupBox();
    GroupBox g2 = new GroupBox();
    GroupBox g3 = new GroupBox();

    g1.Controls.Add(g2);
    g2.Controls.Add(g3);
    g3.Controls.Add(g1);

我不知道这是否有意义,但希望它有所帮助。递归通常被认为是很多人要掌握的“更难”的概念之一。再说一次,我不太善于解释事情。

答案 1 :(得分:0)

正确的术语是递归是正确的。在您发布的链接中,它确实是递归的,因为函数调用自身,这是递归函数的常见属性。

该函数需要接受一个Control实例,因为该函数试图解决问题“对于给定的控件(传入的Control container),找到里面的所有控件。”注意这个方法如何不关心控件的“级别”,无论如何都可以解决它。

你是正确的,如果你在你的例子中运行代码,它将无法正常工作。它只会在“父”控件内的一个级别获取控件。这就是函数需要调用自己的原因。

使用函数调用自身,您将获得以下内容:

使用最外面的控件调用功能  我有孩子吗? 如果是这样,请为每个孩子再次调用相同的功能(这将再次询问孩子的“我有孩子吗?”)。

通过调用函数内部的函数,您将达到所有级别。

警告:请注意,不小心使用的递归会导致问题。如果你将它应用于具有1000个'级别'的东西,你的算法将永远占用并可能崩溃,因为你将耗尽内存来处理它,因为它正在深入挖掘(堆栈溢出!)。另外,我怀疑有一种更好的方法来做你正在做的事情,这样你就不需要使用递归,虽然它会起作用。

希望这有帮助!