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

时间:2022-08-17 15:54:18

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.

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

4 个解决方案

#1


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);        }    }

#2


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 class like this:

基于@ pinkfloydx33的答案以及我对其进行的编辑,我创建了一个扩展方法,使其更加简单,只需创建一个这样的公共静态类:

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 formthis.Enable(false);//Will disable all the controls and sub controls for this formButton1.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.

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

#3


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 Control to 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

#4


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:

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

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);        }    }}

#1


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);        }    }

#2


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 class like this:

基于@ pinkfloydx33的答案以及我对其进行的编辑,我创建了一个扩展方法,使其更加简单,只需创建一个这样的公共静态类:

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 formthis.Enable(false);//Will disable all the controls and sub controls for this formButton1.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.

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

#3


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 Control to 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

#4


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:

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

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);        }    }}