如何在Windows表单中隐藏所有面板?

6
在我的Windows应用程序中,使用了菜单栏和多个面板容器,根据菜单选项显示一个面板。
手动传递名称来隐藏所有面板非常耗时,是否有一种方法可以隐藏所有面板或获取表单中所有面板的名称?

我已编辑了您的标题,请参考“问题的标题应该包含“标签”吗?”,共识是“不应该”。 - John Saunders
你有考虑使用 foreach 循环吗? - Brian
4个回答

10
foreach (Control c in this.Controls)
{
    if (c is Panel) c.Visible = false;
}

你甚至可以将其递归,并传入ControlCollection而不是使用this.Controls

HidePanels(this.Controls);

...

private void HidePanels(ControlCollection controls)
{
    foreach (Control c in controls)
    {
        if (c is Panel)
        {
            c.Visible = false;
        }

        // hide any panels this control may have
        HidePanels(c.Controls);
    }
}

被忍者抢了。我刚才正在写那段代码。现在你有我的赞了。 - Geeky Guy
与其为每种想要执行的操作编写递归遍历控件结构的方法,不如只编写一次方法以获取所有控件(在任何深度)。这样做更容易。 - Servy
@Brian,朋友,回报给你,这就是为什么Stack Overflow有一个叫做体育精神的徽章! - Mike Perrenoud
@Servy,我并不特别反对你的观点。我点了+1赞成你的回答,因为它相当优雅,也许有一天我会采用那段代码。 - Mike Perrenoud

5

假设您想获取表单中任意控件的所有控件,而不仅仅是顶层控件。为此,我们将需要这个非常方便的小助手函数来获取特定控件的所有子控件,包括所有级别:

public static IEnumerable<Control> GetAllControls(Control control)
{
    Stack<Control> stack = new Stack<Control>();
    stack.Push(control);

    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;
        foreach (Control child in next.Controls)
        {
            stack.Push(child);
        }
    }
}

如果您认为会经常使用它,可以将其制作为扩展方法。

然后我们可以在该结果上使用 OfType 来获取特定类型的控件:

var panels = GetAllControls(this).OfType<Panel>();

使用循环而不是递归的好方法(从而避免潜在的堆栈溢出,尽管如果您设法拥有如此深的控制层次结构,您应该退后一步并休息一下...)!我认为,如果您将类型作为通用类型,并仅将与请求的类型匹配的控件推送到堆栈上,它可能会更好一些。也许这不是必要的,嗯... - Joshua
@Joshua 那样做行不通。如果顶层有一个用户控件和一个面板,你想要那个面板吗?如果是的话,那么你不能立即过滤掉你正在寻找的面板,你需要在最后才能这样做。当然,如果你不想返回控件,除非它及其所有父级都是指定类型中的全部,那就是另一回事了。那肯定会更快(你浏览的控件更少),但结果也非常不同。 - Servy
@Joshua 另外请注意,避免递归不仅可以防止任何可能的SO异常,而且通常更具性能。虽然提升不是非常大,但确实存在一定程度上的提升。它还可以防止在调试或处理异常时出现混乱的堆栈跟踪。 - Servy
嗯,如果用“is”包装“yield return”,这样做会不会很简单呢?哦,我懂了,是的,你需要将它们全部推到堆栈上(显然),但我把堆栈和仅保护yield混淆了 - 这样做并不能节省太多精力,与使用“.OfType”扩展方法相比。继续! - Joshua

3

写出这样的代码很简单

foreach (Panel p in this.Controls.OfType<Panel>()) {
    p.Visible = false;
}

1

糟糕!我刚刚还在写代码呢!:P

Control[] aryControls = new Control[]{ controlnamehere1, controlnamehere2 };
foreach (Control ctrl in aryControls)
{
   ctrl.Hide();
}

或者,另一种选择是:
Control[] aryControls = new Control[]{ controlnamehere1, controlnamehere1 };
foreach (Control ctrl in aryControls)
{
   ctrl.Visible = false;
}

你怎么知道控件包含panel1和button1?为什么要创建新的Control[]数组,它会浪费内存,你是想学习不好的习惯吗 - 不必要地浪费内存? - Martin Ch
编辑后更加清晰。你现在只是看我的答案来挖苦我吗? - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接