将表单上的所有控件一次性设置为只读

有没有人有一段代码可以在一个只读的表单中制作所有控件(甚至所有TextBox),而不必将每个控件设置为只读?

通知:

if (_cached == null) { _cached = new List(); foreach(var control in Controls) { TextBox textEdit = control as TextBox; if (textEdit != null) { textEdit.ReadOnly = false; _cached.Add(textEdit); } } } else { foreach(var control in _cached) { control .ReadOnly = false; } } 

同时添加递归(控件可以放入其他控件(面板))。

编写一个扩展方法,收集指定类型的控件和子控件:

 public static IEnumerable GetChildControls(this Control control) where T : Control { var children = control.Controls.OfType(); return children.SelectMany(c => GetChildControls(c)).Concat(children); } 

在表单上收集TextBoxes(使用TextBoxBase来影响RichTextBox等 – @ Timwi的解决方案):

 IEnumerable textBoxes = this.GetChildControls(); 

通过集合迭代并设置只读:

 private void AreTextBoxesReadOnly(IEnumerable textBoxes, bool value) { foreach (TextBoxBase tb in textBoxes) tb.ReadOnly = value; } 

如果想要 – 使用缓存 – @ igor的解决方案

您应该能够自己编写一个实用程序函数来执行此操作。 您可以迭代窗体的控件,然后递归地控制每个控件的子控件。 例如:

 public static void SetEnableOnAllControls(Control parentControl, bool enable) { parentControl.Enabled = enable; foreach (Control control in parentControl.Controls) SetEnableOnAllControls(control, enable); } [...] // inside your form: SetEnableOnAllControls(this, false); 

这不会处理ToolStrip ,它们不是控件。 您可以为这些方法编写单独的类似方法。

请注意,上面也禁用了表单本身。 如果你不想那样,试试这个:

 public static void SetEnableOnAllChildControls(Control parentControl, bool enable) { foreach (Control control in parentControl.Controls) { control.Enabled = enable; SetEnableOnAllChildControls(control, enable); } } 

如果你真的是指ReadOnly属性,它只与TextBoxes有关,试试这个:

 public static void SetReadOnlyOnAllControls(Control parentControl, bool readOnly) { if (parentControl is TextBoxBase) ((TextBoxBase) parentControl).ReadOnly = readOnly; foreach (Control control in parentControl.Controls) SetReadOnlyOnAllControls(control, readOnly); } 
 this.Enabled = false; 

取决于你真正做的事情,你可能想要考虑将控件放在一个面板中并禁用它。

我没有测试过这个,但它应该工作:

 foreach (var textBox in this.Controls.OfType()) textBox.ReadOnly = true; 

编辑:这似乎不是一个很好的解决方案:看看蒂姆维的评论。

我会使用reflection来检查通用Control对象是否具有Enabled属性。

 private static void DisableControl(Control control) { PropertyInfo enProp = control.GetType().GetProperty("Enabled"); if (enProp != null) { enProp.SetValue(control, false, null); } foreach (Control ctrl in control.Controls) { DisableControl(ctrl); } } 

我刚刚开发了一个递归解决方案,使用简单的静态方法和ASP.NET多态来处理任何类型的Web控件。

 ///  /// Handle "Enabled" property of a set of Controls (and all of the included child controls through recursivity) /// By default it disable all, making all read-only, but it can also be uset to re-enable everything, using the "enable" parameter ///  /// Set of controls to be handled. It could be the entire Page.Controls set or all of the childs of a given control (property "Controls" of any Control-derived class) /// Desired value of the property "enable" of each control.  public static void DisableControls(ControlCollection controls, bool enable = false) { foreach (Control control in controls) { var wCtrl = control as WebControl; if (wCtrl != null) { wCtrl.Enabled = enable; } if (control.Controls.Count > 0) DisableControls(control.Controls, enable); } } ///  /// Enable a set of Controls (and all of the included child controls through recursivity). /// Friendly name for DisableControls(controls, true), that achieve the same result. ///  /// Set of controls to be handled. It could be the entire Page.Controls set or all of the childs of a given control (property "Controls" of any Control-derived class) public static void EnableControls(ControlCollection controls) { DisableControls(controls, true); } 

这是经过测试并且看起来相当快(在Web表单中不到一毫秒,其中25个控件被禁用)。

如果您更喜欢扩展方法,我认为应该足以更改解决方案,如下所示:

 public static void DisableControls(this Control control, bool enable = false) { foreach (Control ctrl in control.Controls) { var wCtrl = ctrl as WebControl; if (wCtrl != null) { wCtrl.Enabled = enable; } if (ctrl.Controls.Count > 0) ctrl.DisableControls(enable); } } public static void EnableControls(this Control control) { control.DisableControls(true); }