You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改NestedControls方法以直接返回指定类型的容器控件?

问题

我现在用下面这个扩展方法获取容器里的所有嵌套控件:

public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true)
{
    var stack = new Stack<Control>();
    stack.Push(container);
    do
    {
        var control = stack.Pop();

        foreach (Control child in control.Controls)
        {
            yield return child;
            stack.Push(child);
        }
    }
    while (stack.Count > 0 && search_all_children);
}

目前我只能通过这种方式筛选指定类型的控件,比如TextBox:

var textboxes = panel1.NestedControls().OfType<TextBox>().ToList();

我想修改这个方法,让它支持直接通过 panel1.NestedControls<TextBox>() 这样的调用获取指定类型的控件,该怎么改?

解决方案

你可以给方法加上泛型支持,直接在遍历过程中筛选目标类型,下面提供两种实用实现方式:

方式一:新增泛型重载(保留原方法兼容旧代码)

保留原来的无类型方法,新增一个泛型版本的重载,这样新旧调用逻辑都能正常运行:

// 原方法保持不变,兼容之前的调用
public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true)
{
    var stack = new Stack<Control>();
    stack.Push(container);
    do
    {
        var control = stack.Pop();

        foreach (Control child in control.Controls)
        {
            yield return child;
            stack.Push(child);
        }
    }
    while (stack.Count > 0 && search_all_children);
}

// 新增泛型扩展方法,直接返回指定类型控件
public static IEnumerable<T> NestedControls<T>(this Control container, bool search_all_children = true) where T : Control
{
    var stack = new Stack<Control>();
    stack.Push(container);
    do
    {
        var control = stack.Pop();

        foreach (Control child in control.Controls)
        {
            // 直接匹配并转换为目标类型,符合条件才返回
            if (child is T typedChild)
            {
                yield return typedChild;
            }
            stack.Push(child);
        }
    }
    while (stack.Count > 0 && search_all_children);
}

调用示例:

// 获取所有TextBox控件
var textboxes = panel1.NestedControls<TextBox>().ToList();
// 获取所有Button控件
var buttons = panel1.NestedControls<Button>().ToList();

方式二:合并为泛型方法(通过包装兼容旧调用)

如果不想维护两个方法,可以把核心逻辑改成泛型实现,再套一层非泛型的包装方法:

// 泛型核心方法,限定T必须是Control子类
public static IEnumerable<T> NestedControls<T>(this Control container, bool search_all_children = true) where T : Control
{
    var stack = new Stack<Control>();
    stack.Push(container);
    do
    {
        var control = stack.Pop();

        foreach (Control child in control.Controls)
        {
            if (child is T typedChild)
            {
                yield return typedChild;
            }
            stack.Push(child);
        }
    }
    while (stack.Count > 0 && search_all_children);
}

// 非泛型包装方法,兼容原有调用逻辑
public static IEnumerable<Control> NestedControls(this Control container, bool search_all_children = true)
{
    return container.NestedControls<Control>(search_all_children);
}

这种写法下,panel1.NestedControls()和panel1.NestedControls<TextBox>()都能正常使用。

关键说明

  • 泛型约束where T : Control能确保传入的类型是Control的子类,避免无效类型传入导致错误。
  • 遍历过程中直接筛选转换,比先返回所有控件再用OfType<T>更高效,减少了后续的集合操作开销。

内容的提问来源于stack exchange,提问作者Quince

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:30:02