后续:找到控制的孩子
本文关键字:孩子 控制 后续 | 更新日期: 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个"关卡"的内容,你的算法将花费很长时间并且可能会崩溃,因为你将耗尽内存来处理它,因为它正在越来越深地挖掘(堆栈溢出!)。另外,我怀疑有一种更好的方法来完成您正在做的事情,这样您就不需要使用递归,尽管它可以工作。
希望这对你有帮助!