我想在我的表单上的所有文本框中添加一个事件:
foreach (Control C in this.Controls)
{
if (C.GetType() == typeof(System.Windows.Forms.TextBox))
{
C.TextChanged += new EventHandler(C_TextChanged);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是它们存储在几个组框中,而我的循环看不到它们.我可以单独循环遍历每个组框的控件,但是可以在一个循环中以简单的方式完成所有操作吗?
Oli*_*bes 32
ControlsForms和容器控件的集合仅包含直接子项.为了获得所有控件,您需要遍历控件树并递归地应用此操作
private void AddTextChangedHandler(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c.GetType() == typeof(TextBox)) {
c.TextChanged += new EventHandler(C_TextChanged);
} else {
AddTextChangedHandler(c);
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:表单也是(间接)派生的Control,所有控件都有一个Controls集合.所以你可以在你的表单中调用这样的方法:
AddTextChangedHandler(this);
Run Code Online (Sandbox Code Playgroud)
更通用的解决方案是创建一个递归方法,以递归方式将操作应用于所有控件.在静态类(例如WinFormsExtensions)中添加此方法:
public static void ForAllControls(this Control parent, Action<Control> action)
{
foreach (Control c in parent.Controls) {
action(c);
ForAllControls(c, action);
}
}
Run Code Online (Sandbox Code Playgroud)
静态类命名空间必须是"可见的",即using如果它在另一个命名空间中,则添加适当的声明.
然后你就可以这样称呼它,this表格在哪里; 您还可以替换this其嵌套控件必须受影响的窗体或控件变量:
this.ForAllControls(c =>
{
if (c.GetType() == typeof(TextBox)) {
c.TextChanged += C_TextChanged;
}
});
Run Code Online (Sandbox Code Playgroud)
Ser*_*rvy 13
一些简单的通用工具使这个问题变得非常简单.我们可以创建一个简单的方法来遍历整个控件的树,返回其所有子节点的序列,所有子节点等等,覆盖所有控件,而不仅仅是固定深度.我们可以使用递归,但通过避免递归它会表现得更好.
public static IEnumerable<Control> GetAllChildren(this Control root)
{
var stack = new Stack<Control>();
stack.Push(root);
while (stack.Any())
{
var next = stack.Pop();
foreach (Control child in next.Controls)
stack.Push(child);
yield return next;
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个我们可以得到所有的孩子,过滤掉我们需要的类型,然后非常容易地附加处理程序:
foreach(var textbox in GetAllChildren().OfType<Textbox>())
textbox.TextChanged += C_TextChanged;
Run Code Online (Sandbox Code Playgroud)
试试这个
AllSubControls(this).OfType<TextBox>().ToList()
.ForEach(o => o.TextChanged += C_TextChanged);
Run Code Online (Sandbox Code Playgroud)
AllSubControls在哪里
private static IEnumerable<Control> AllSubControls(Control control)
=> Enumerable.Repeat(control, 1)
.Union(control.Controls.OfType<Control>()
.SelectMany(AllSubControls)
);
Run Code Online (Sandbox Code Playgroud)
LINQ很棒!
正如您所说,您必须更深入地了解表单中的每个元素。不幸的是,这意味着使用嵌套循环。
在第一个循环中,循环遍历每个元素。如果元素的类型为 GroupBox,那么您知道在继续之前需要循环遍历 groupbox 内的每个元素;否则照常添加事件。
您似乎对 C# 有很好的掌握,所以我不会给您任何代码;纯粹是为了确保您掌握解决问题所涉及的所有重要概念:)