我的表单有数百个控件:菜单、面板、拆分器、标签、文本框,应有尽有。
有没有办法禁用除单个按钮之外的所有控件?
按钮很重要的原因是因为我不能使用禁用窗口或其他东西的方法,因为一个控件仍然需要可用。
您可以进行递归调用以禁用所有涉及的控件。然后你必须启用你的按钮和任何父容器。
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);
}
}
基于@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
{
}
}
}
}
现在,要启用或禁用控件、表单、菜单、子控件等。只需执行以下操作:
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
所以,我会做什么,类似于@pinkfloydx33 的回答:
private void Form1_Load(object sender, EventArgs e)
{
this.Enable(false);
Button1.Enable(true);
}
我喜欢扩展方法,因为它们是静态的,您可以在任何地方使用它而无需(手动)创建实例,而且至少对我来说更清晰。
要获得更好、更优雅且易于维护的解决方案 - 您可能需要重新考虑您的设计,例如将您的按钮与其他控件分开。然后假设其他控件在面板或组框中,只需执行Panel.Enabled = False
.
如果您真的想保留当前的设计,可以将ControlCollection 树线性化为 Control 数组以避免递归,然后执行以下操作:
Array.ForEach(Me.Controls.GetAllControlsOfType(Of Control), Sub(x As Control) x.Enabled = False)
yourButton.Enabled = True
当您嵌套了许多面板或 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);
}
}
}
我已经更正了@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
{
}
}
}