4

我们如何将 Winform 中所有文本框的 ReadOnly 属性更改为 true 到 false 我正在尝试使用此代码,但这提示我对象空引用错误...

    private void TextBoxesReadOnlyTrue(Control.ControlCollection cc)
    {
        foreach (Control ctrl in cc)
        {
            TextBox tb = ctrl as TextBox;
            if (tb.ReadOnly)
             {
                tb.ReadOnly = false;
             }

        }
    } 
4

2 回答 2

6

那是因为并非 cc 中的所有控件都是 TextBox。因此,当您尝试将它们转换为 TextBox 时,该变量为空。当变量为 null 时,您无法访问该变量的任何属性,否则会出现错误。所以任何时候一个变量可以为空,你必须首先测试它是否为空。

这是您要用来解决问题的修改后的 if 命令:

    if (tb != null && tb.ReadOnly) { tb.ReadOnly = false; }

所以我很抱歉我忽略了您的 TextBoxes 可以包含在其他容器控件中。是的,这意味着您需要做 2 件事中的 1 件事: 1:您可以将 TextBoxes 移到 GroupBox 之外。哈哈。我只是在开玩笑。是的,这可以解决这个问题,但你会遇到更严重的问题。Controls正确的方法是为每个在其属性中具有控件的控件递归调用您的方法。每个控件都有这个属性,但在不是容器的控件中它似乎是空的(但不是 null)。(我今天刚刚了解到每个控件都有这个Controls属性,所以我更新了我的代码以反映这一点。)所以对于这个真正的解决方案,我建议类似这样的东西:

private void TextBoxesReadOnlyTrue(Control.ControlCollection cc)
{
    foreach (Control ctrl in cc)
    {
        TextBox tb = ctrl as TextBox;
        if (tb != null && tb.ReadOnly)
        { tb.ReadOnly = false; continue; }

        if (ctrl.Controls != null && ctrl.Controls.Count > 0)
        { TextBoxesReadOnlyTrue(ctrl.Controls); }
        // this recursively calls this same method for every control ...
        // that is a container control that contains more controls, ...
        // such as GroupBoxes, Panels, etc.
    }
}
于 2013-10-30T02:26:08.440 回答
2

首先你想使用这样的函数:

递归获取控件

然后你做以下

private IEnumerable<T> GetControls<T>(Control.ControlCollection ctrls)
{
    foreach (object ctrl in ctrls)
    {
        foreach (var item in GetControls<T>(((Control)ctrl).Controls))
        {
            yield return item;    
        } 
        if (ctrl is T)
           yield return (T)ctrl;

    }
}

foreach(var txtbox in  GetControls<TextBox>(form.Controls)
{
    txtbox.ReadOnly = false;
}
于 2013-10-30T08:05:55.530 回答