【问题标题】:Make all Controls on a Form read-only at once一次将表单上的所有控件设为只读
【发布时间】:2011-04-06 20:05:18
【问题描述】:

有没有人有一段代码可以使表单中的所有控件(甚至所有文本框)一次只读,而不必将每个控件单独设置为只读?

【问题讨论】:

  • @Raulp 我不认为“这是”在这里是正确的。表单不是只读的,但控件应该是。

标签: c# .net vb.net winforms


【解决方案1】:
this.Enabled = false;

取决于您实际执行的操作,您可能需要考虑将控件放在面板中并禁用它。

【讨论】:

  • 很酷的解决方案。如果将它与 它变得相当不错。剩下的缺点是用户不能选择文本和复制。
【解决方案2】:

您应该能够为自己编写一个实用函数来执行此操作。您可以遍历表单的控件,然后递归地遍历每个控件的子控件。例如:

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 控件不是容器。
【解决方案3】:

我没有对此进行测试,但它应该可以工作:

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

编辑:这似乎不是一个很好的解决方案:请参阅 Timwi 的评论。

【讨论】:

  • ① 不考虑嵌套控件,即只对顶层控件起作用; ② 应该使用TextBoxBase,这样它也会影响其他类似文本框的控件(例如RichTextBox)。
【解决方案4】:

形式:

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;
    }
}

还添加递归(控件可以放置到其他控件(面板)中)。

【讨论】:

  • 我认为存储在缓存中可以提高性能。但是,您必须考虑允许用户刷新缓存。您的代码也不会遍历嵌套控件(例如放置在面板内的文本框)。总的来说,这是一个很好的解决方案。
  • @Alex Essilfie 我写道:“也添加递归”:),没有任何关于动态代码创建以重置 _cache 的提及(请参阅“in Form” no out of Form)。谢谢。
【解决方案5】:

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

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 的解决方案

【讨论】:

  • 它不会从 panel/gb 返回文本框。
【解决方案6】:

我会使用反射来检查通用 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);
    }
}

【讨论】:

    【解决方案7】:

    我刚刚使用简单的静态方法和 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      相关资源
      最近更新 更多