【发布时间】:2011-04-06 20:05:18
【问题描述】:
有没有人有一段代码可以使表单中的所有控件(甚至所有文本框)一次只读,而不必将每个控件单独设置为只读?
【问题讨论】:
-
@Raulp 我不认为“这是”在这里是正确的。表单不是只读的,但控件应该是。
有没有人有一段代码可以使表单中的所有控件(甚至所有文本框)一次只读,而不必将每个控件单独设置为只读?
【问题讨论】:
this.Enabled = false;
取决于您实际执行的操作,您可能需要考虑将控件放在面板中并禁用它。
【讨论】:
您应该能够为自己编写一个实用函数来执行此操作。您可以遍历表单的控件,然后递归地遍历每个控件的子控件。例如:
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);
这不涉及ToolStrips,它们不是控件。你可以为它们编写一个单独的、类似的方法。
请注意,上述内容也会禁用表单本身。如果你不想这样,试试这个:
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);
}
【讨论】:
else 放入最后一个sn-p:TextBox 控件不是容器。
我没有对此进行测试,但它应该可以工作:
foreach (var textBox in this.Controls.OfType<TextBox>())
textBox.ReadOnly = true;
编辑:这似乎不是一个很好的解决方案:请参阅 Timwi 的评论。
【讨论】:
TextBoxBase,这样它也会影响其他类似文本框的控件(例如RichTextBox)。
形式:
if (_cached == null)
{
_cached = new List<TextBox>();
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<T> GetChildControls<T>(this Control control) where T : Control
{
var children = control.Controls.OfType<T>();
return children.SelectMany(c => GetChildControls<T>(c)).Concat(children);
}
在表单上收集文本框(使用TextBoxBase 影响RichTextBox 等 - @Timwi 的解决方案):
IEnumerable<TextBoxBase> textBoxes = this.GetChildControls<TextBoxBase>();
遍历集合并设置为只读:
private void AreTextBoxesReadOnly(IEnumerable<TextBoxBase> textBoxes, bool value)
{
foreach (TextBoxBase tb in textBoxes) tb.ReadOnly = value;
}
如果需要 - 使用缓存 - @igor 的解决方案
【讨论】:
我会使用反射来检查通用 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 控件的递归解决方案。
/// <summary>
/// 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
/// </summary>
/// <param name="controls">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)</param>
/// <param name="enable">Desired value of the property "enable" of each control. </param>
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);
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="Controls">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)</param>
public static void EnableControls(ControlCollection controls)
{
DisableControls(controls, true);
}
这是经过测试的,看起来相当快(在禁用 25 多个控件的 Web 表单中不到一毫秒)。
如果您更喜欢扩展方法,我认为将解决方案更改如下就足够了:
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);
}
【讨论】: