通过反射设置 winform 面板名称时,将 visible 设置为 true 失败。为什么?

When setting winform panel name by reflection, setting visible to true fails. Why?

我正在尝试遍历许多默认设置为 .Visible = false 的面板。我想将这些更改为 true,但我只会在 运行 时间知道哪些。

我有以下代码:

var genericPanel =  new Panel();
            var myName = "panel" + i;
            PropertyInfo prop = genericPanel.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
            if (null != prop && prop.CanWrite)
            {
                prop.SetValue(genericPanel, myName, null);
            }

            genericPanel.Enabled = true;
            genericPanel.Visible = true;
            var blah = genericPanel.Name;  // Name is correct
            Application.DoEvents();

            // This works fine
            //panel1.Visible = true;
            //panel1.Enabled = true;
            //Application.DoEvents();

使用反射我似乎能够正确设置对象名称,但我尝试设置可见性和启用的属性失败了。直接这样做就好了。

我错过了什么?

您需要将面板添加到表单(或某些容器)的控件中。

您可能已经有一个让您感到困惑的 panel1:

var genericPanel = new Panel();
var myName = "panel" + 3;
PropertyInfo prop = genericPanel.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
if (null != prop && prop.CanWrite)
{
    prop.SetValue(genericPanel, myName, null);
}
genericPanel.Enabled = true;
genericPanel.Visible = true;
genericPanel.BackColor = Color.Red;

this.Controls.Add(genericPanel);

我认为您不需要为此使用 System.Reflection。您正在错误的代码中创建新面板。您应该执行以下操作:

private void SetControlVisibility(string controlName, bool visible)
{
    // Searches through all controls inside your Form recursively by controlName
    Control control = GetControlByName(this.Controls, controlName);

    if (control != null)
        control.Visible = visible;
}

private Control GetControlByName(Control.ControlCollection controls, string controlName)
{
    Control controlToFind = null;

    foreach (Control control in controls)
    {
        // If control is container like panel or groupBox, look inside it's child controls
        if (control.HasChildren)
        {
            controlToFind = GetControlByName(control.Controls, controlName);

            // If control is found inside child controls, break the loop
            // and return the control
            if (controlToFind != null)
                break;
        }

        // If current control name is the name you're searching for, set control we're
        // searching for to that control, break the loop and return the control
        if (control.Name == controlName)
        {
            controlToFind = control;
            break;
        }
    }

    return controlToFind;
}

用例示例:

int i = 3;
string controlName= "panel" + i; // I'm hiding green panel (panel3)
SetControlVisibility(controlName, false);

之前:

之后:

编辑:

按照评论中的建议,也可以使用Control.ControlCollectionFind方法。它看起来像这样:

// True flag is to search through all nested child controls
Control[] controls = this.Controls.Find(panelName, true);
if (controls != null)
    controls[0].Visible = false;