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?
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);
}
}
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
.
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:
Array.ForEach(Me.Controls.GetAllControlsOfType(Of Control), Sub(x As Control) x.Enabled = False)
yourButton.Enabled = True
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:
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);
}
}
}
I have corrected @coloboxp answer, first you must enable all parents:
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
{
}
}
}
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:
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:
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.