我认为正确的术语是递归。我有一个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
再次感谢你。我喜欢听到你们所有人的意见,因为这对我来说是一次极好的学习经历。
非常感谢你的时间。
答案 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个'级别'的东西,你的算法将永远占用并可能崩溃,因为你将耗尽内存来处理它,因为它正在深入挖掘(堆栈溢出!)。另外,我怀疑有一种更好的方法来做你正在做的事情,这样你就不需要使用递归,虽然它会起作用。
希望这有帮助!