C# 如何禁用表单上除按钮之外的所有控件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13446129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:34:53  来源:igfitidea点击:

How to disable all controls on the form except for a button?

c#winformscontrols

提问by Ryan Peschel

My form has hundreds of controls: menus, panels, splitters, labels, text boxes, you name it.

我的表单有数百个控件:菜单、面板、拆分器、标签、文本框,您可以随意命名。

Is there a way to disable every control except for a single button?

有没有办法禁用除单个按钮之外的所有控件?

The reason why the button is significant is because I can't use a method that disables the window or something because one control still needs to be usable.

按钮之所以重要,是因为我不能使用禁用窗口或其他东西的方法,因为一个控件仍然需要可用。

回答by pinkfloydx33

You can do a recursive call to disable all of the controls involved. Then you have to enable your button and any parent containers.

您可以执行递归调用以禁用所有涉及的控件。然后你必须启用你的按钮和任何父容器。

 private void Form1_Load(object sender, EventArgs e) {
        DisableControls(this);
        EnableControls(Button1);
    }

    private void DisableControls(Control con) {
        foreach (Control c in con.Controls) {
            DisableControls(c);
        }
        con.Enabled = false;
    }

    private void EnableControls(Control con) {
        if (con != null) {
            con.Enabled = true;
            EnableControls(con.Parent);
        }
    }

回答by Neolisk

For a better, more elegant solution, which would be easy to maintain - you probably need to reconsider your design, such as put your button aside from other controls. Then assuming other controls are in a panel or a groupbox, just do Panel.Enabled = False.

为了获得更好、更优雅、易于维护的解决方案 - 您可能需要重新考虑您的设计,例如将您的按钮与其他控件放在一起。然后假设其他控件在面板或组框中,只需执行Panel.Enabled = False.

If you really want to keep your current design, you can Linearise ControlCollection tree into array of Controlto avoid recursion and then do the following:

如果您真的想保留当前的设计,您可以将ControlCollection 树线性化为 Control 数组以避免递归,然后执行以下操作:

Array.ForEach(Me.Controls.GetAllControlsOfType(Of Control), Sub(x As Control) x.Enabled = False)
yourButton.Enabled = True

回答by coloboxp

Based on @pinkfloydx33's answer and the edit I made on it, I created an extension method that makes it even easier, just create a public static classlike this:

基于@pinkfloydx33 的回答和我对它所做的编辑,我创建了一个扩展方法,使它更容易,只需创建一个public static class这样的:

public static class GuiExtensionMethods
{
        public static void Enable(this Control con, bool enable)
        {
            if (con != null)
            {
                foreach (Control c in con.Controls)
                {
                    c.Enable(enable);
                }

                try
                {
                    con.Invoke((MethodInvoker)(() => con.Enabled = enable));
                }
                catch
                {
                }
            }
        }
}

Now, to enable or disable a control, form, menus, subcontrols, etc. Just do:

现在,要启用或禁用控件、表单、菜单、子控件等。只需执行以下操作:

this.Enable(true); //Will enable all the controls and sub controls for this form
this.Enable(false);//Will disable all the controls and sub controls for this form

Button1.Enable(true); //Will enable only the Button1

So, what I would do, similar as @pinkfloydx33's answer:

所以,我会怎么做,类似于@pinkfloydx33 的回答:

private void Form1_Load(object sender, EventArgs e) 
{
        this.Enable(false);
        Button1.Enable(true);
}

I like Extension methods because they are static and you can use it everywhere without creating instances (manually), and it's much clearer at least for me.

我喜欢扩展方法,因为它们是静态的,你可以在任何地方使用它而无需创建实例(手动),至少对我来说更清晰。

回答by Yayo Bruno

When you have many panels or tableLayoutPanels nested the situation becomes tricky. Trying to disable all controls in a panel disabling the parent panel and then enabling the child control does not enable the control at all, because the parent (or the parent of the parent) is not enabled. In order to keep enabled the desired child control I saw the form layout as a tree with the form itself as the root, any container or panel as branches and child controls (buttons, textBoxes, labels, etc.) as leaf nodes. So, the main goal is to disable all nodes within the same level as the desired control, climbing up the control tree all the way to the form level, stablishing a path of enabled controls so the child one can work:

当您有许多面板或 tableLayoutPanel 嵌套时,情况变得棘手。尝试禁用面板中的所有控件禁用父面板然后启用子控件根本不会启用该控件,因为未启用父级(或父级的父级)。为了保持启用所需的子控件,我将表单布局视为一棵树,表单本身作为根,任何容器或面板作为分支,子控件(按钮、文本框、标签等)作为叶节点。因此,主要目标是禁用与所需控件相同级别内的所有节点,将控件树一直向上爬到表单级别,建立启用控件的路径,以便子控件可以工作:

public static void DeshabilitarControles(Control control)
{
    if (control.Parent != null)
    {
        Control padre = control.Parent;
        DeshabilitarControles(control, padre);
    }
}

private static void DeshabilitarControles(Control control, Control padre)
{
    foreach (Control c in padre.Controls)
    {
        c.Enabled = c == control;
    }
    if (padre.Parent != null)
    {
        control = control.Parent;
        padre = padre.Parent;
        DeshabilitarControles(control, padre);
    }
}

public static void HabilitarControles(Control control)
{
    if (control != null)
    {
        control.Enabled = true;
        foreach (Control c in control.Controls)
        {
            HabilitarControles(c);
        }
    }
}

回答by Andreas_k

I have corrected @coloboxp answer, first you must enable all parents:

我已更正@coloboxp 答案,首先您必须启用所有父母:

    public static void Enable(this Control con, bool enable)
    {
        if (con != null)
        {
            if (enable)
            {
                Control original = con;

                List<Control> parents = new List<Control>();
                do
                {
                    parents.Add(con);

                    if (con.Parent != null)
                        con = con.Parent;
                } while (con.Parent != null && con.Parent.Enabled == false);

                if (con.Enabled == false)
                    parents.Add(con); // added last control without parent

                for (int x = parents.Count - 1; x >= 0; x--)
                {
                    parents[x].Enabled = enable;
                }

                con = original;
                parents = null;
            }

            foreach (Control c in con.Controls)
            {
                c.Enable(enable);
            }

            try
            {
                con.Invoke((MethodInvoker)(() => con.Enabled = enable));
            }
            catch
            {
            }
        }
    }