通过反射设置 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.ControlCollection
的Find
方法。它看起来像这样:
// True flag is to search through all nested child controls
Control[] controls = this.Controls.Find(panelName, true);
if (controls != null)
controls[0].Visible = false;
我正在尝试遍历许多默认设置为 .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.ControlCollection
的Find
方法。它看起来像这样:
// True flag is to search through all nested child controls
Control[] controls = this.Controls.Find(panelName, true);
if (controls != null)
controls[0].Visible = false;