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

时间:2010-09-01 13:56:38

标签: c# .net vb.net winforms

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

7 个答案:

答案 0 :(得分:6)

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

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

在表单上收集TextBoxes(使用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的解决方案

答案 1 :(得分:5)

表格:

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

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

答案 2 :(得分:4)

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

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 s,它们不是控件。您可以为这些方法编写一个单独的类似方法。

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

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

答案 3 :(得分:2)

this.Enabled = false;

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

答案 4 :(得分:2)

我没有对此进行测试,但它应该有效:

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

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

答案 5 :(得分:2)

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

答案 6 :(得分:0)

我刚开发了一个递归解决方案,使用简单的静态方法和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个以上的控件被禁用)。

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

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