Как отключить все элементы управления в форме, кроме кнопки?
Моя форма содержит сотни элементов управления: меню, панели, разделители, метки, текстовые поля, которые вы называете.
Есть ли способ отключить каждый элемент управления, за исключением одной кнопки?
Причина, по которой кнопка важна, заключается в том, что я не могу использовать метод, который отключает окно или что-то, потому что один элемент управления все еще должен использоваться.
Ответы
Ответ 1
Вы можете сделать рекурсивный вызов, чтобы отключить все задействованные элементы управления. Затем вам нужно включить свою кнопку и любые родительские контейнеры.
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
На основе ответа @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);
}
Мне нравятся методы расширения, потому что они являются статическими, и вы можете использовать его везде, не создавая экземпляры (вручную), и это гораздо яснее, по крайней мере для меня.
Ответ 3
Для лучшего, более элегантного решения, которое было бы легко поддерживать - вам, вероятно, придется пересмотреть свой дизайн, например, оставить свою кнопку в стороне от других элементов управления. Затем, предполагая, что другие элементы управления находятся в панели или групповом ящике, просто выполните Panel.Enabled = False
.
Если вы действительно хотите сохранить свой текущий дизайн, вы можете линеаризовать дерево ControlCollection в массив Control, чтобы избежать рекурсии, а затем выполните следующие действия:
Array.ForEach(Me.Controls.GetAllControlsOfType(Of Control), Sub(x As Control) x.Enabled = False)
yourButton.Enabled = True
Ответ 4
Когда у вас много вложенных панелей или таблиц 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);
}
}
}
Ответ 5
Я исправил ответ @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
{
}
}
}