如果将Windows窗体控件的Visible属性设置为true,则在隐藏任何控件的父窗口时,该属性仍会返回false。有没有办法在隐藏父窗口的情况下获取控件的真实底层可见性标志?
答案 0 :(得分:13)
好吧,常规实现会检查控件堆栈,以确保所有父项都可见。我知道躲避这一点的唯一方法是用反思欺骗,并要求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 });
答案 1 :(得分:2)
我所做的是暂时从其父控件中删除该按钮以检查其Visible值,然后重新添加到父控件。
如果需要,您可以跟踪子索引以在正确的索引处重新添加它。
答案 2 :(得分:0)
不依赖于反射的选项是通过控件层次结构的父级递归,查找Visible设置为false的父级。
编辑:请参阅评论,了解代码的重要性。
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);
答案 3 :(得分:0)
我对从'ToolStripItem'基类派生的类有同样的问题。所以我用Available属性值检查是否显示项目。问题解决了。样品:
ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();
在此示例中,'curItm'是ToolStripItem派生类的一个实例。
依赖于父容器的Visible / Enabled的.Net控件中的Visible / Enabled属性的这个问题必须由.Net团队解决。 我在自己的类中创建一个名为IsVisible / IsEnabled的服装属性,它返回Visible / Enabled属性的赋值,而不是依赖于父容器的值。