将表单上的所有控件一次性设置为只读
有没有人有一段代码可以在一个只读的表单中制作所有控件(甚至所有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); }