后续:找到控制的孩子

本文关键字:孩子 控制 后续 | 更新日期: 2023-09-27 17:53:22

我认为适当的术语是递归。我有一个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

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

感谢您的宝贵时间。

后续:找到控制的孩子

private void FindAll(Control myControl)
{
    if (myControl is Button)
        doStuff();
    foreach (Control myChild in myControl.Controls)            
        FindAll(myChild);
}

我相信这是可行的。当你第一次调用它时,你会传入表单。表单不是按钮,但它有子窗体。它拥有的每一个子元素都将被传递给FindAll()。如果那个控件是一个按钮,它将调用doStuff()(您可以在那里设置光标)。同样,如果该控件有任何子控件,它们将被传入。

你是正确的,术语是递归的(一般来说,任何函数或子调用自己)。因此,在本例中,FindAll()将在特定情况下调用FindAll()。

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

编辑:如果你不熟悉递归,那么很容易得到可怕的StackOverflow异常。当你在一个永无止境的循环中结束调用自己时,你将耗尽stackspace并看到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);

我不知道这是否有意义,但希望它能有所帮助。对于很多人来说,递归通常被认为是"较难"掌握的概念之一。不过,我也不太擅长解释事情。

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

该函数需要一个Control实例,因为该函数试图解决"对于给定的控件(即传入的Control container),找到其中的所有控件"的问题。注意这个方法不关心控件的"级别",它可以解决它。

你是正确的,如果你在你的例子中运行代码,它不会工作。它只会拾取"父"控件中的一个级别的控件。这就是为什么函数需要调用自己。

通过调用函数本身,可以得到以下结果:

具有最外层控件的调用函数。
我有孩子吗?
如果是,为每个子节点再次调用相同的函数(这将再次询问"Do I have any children?")。

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

WARNING:请注意,不小心使用递归可能会导致问题。如果你将此应用于具有1000个"关卡"的内容,你的算法将花费很长时间并且可能会崩溃,因为你将耗尽内存来处理它,因为它正在越来越深地挖掘(堆栈溢出!)。另外,我怀疑有一种更好的方法来完成您正在做的事情,这样您就不需要使用递归,尽管它可以工作。

希望这对你有帮助!