如果将Windows窗体控件的Visible属性设置为true,则如果任何一个父窗口隐藏了,该属性仍然返回false。是否有办法在父窗口隐藏的情况下获取控件真正的可见性标志?
正常的实现确实会检查控制堆栈,以确保所有父级都是可见的。我所知道的唯一规避此问题的方法是使用反射欺骗,并请求GetState(2)
,但这种方法很容易出错:
// dodgy; not recommended
Panel query;
Form form = new Form
{
Controls = {
new Panel {
Visible = false,
Controls = {
(query = new Panel {Visible = true})
}
}
}
};
form.Show();
// this is the dodgy bit...
bool visible = (bool)typeof(Control)
.GetMethod("GetState", BindingFlags.Instance | BindingFlags.NonPublic)
.Invoke(query, new object[] { 2 });
我所做的是暂时将按钮从其父控件中移除,以检查其 Visible 值,然后重新添加到父控件中。
如果需要,您可以跟踪子索引以在正确的索引处重新添加它。
我遇到了与派生自“ToolStripItem”基类的类相同的问题。因此,我使用了“Available”属性值来检查项目是否会显示。问题得到解决。样例:
ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();
var frm2 = new Form {Text = "Form2"}; var lbl = new Label {Visible = true}; frm2.Controls.Add(lbl); frm2.Show();
var frm1 = new Form {Text = "Form1"}; var lblVis = new Label { Text = lbl.Visible.ToString(), Left = 10, Top = 10}; lbl.VisibleChanged += (sender, args) => MessageBox.Show("Label Visible changed"); var btnShow = new Button {Text = "Show", Left = 10, Top = lblVis.Bottom + 10}; btnShow.Click += (sender, args) => { frm2.Visible = true; lblVis.Text = lbl.Visible.ToString(); }; var btnHide = new Button {Text = "Hide", Left = 10, Top = btnShow.Bottom + 10}; btnHide.Click += (sender, args) => { frm2.Visible = false; lblVis.Text = lbl.Visible.ToString(); };
frm1.Controls.AddRange(new Control[] {lblVis, btnShow, btnHide});
Application.Run(frm1);