If you set the Visible property of a Windows Forms control to true, that property still returns false if any of the control's parent windows are hidden. Is there a way to get the true, underlying visibility flag of the control in case the parent window is hidden?
4 Answers
Well, the regular implementation does check up the control stack, to ensure that all parents are visible. The only way I know to dodge this is to cheat with reflection, and ask for GetState(2)
, but that is brittle:
// 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 });

- 6,904
- 2
- 23
- 38

- 1,026,079
- 266
- 2,566
- 2,900
-
What is the 2? Is there a constant or enum you can use instead? – Jon B Dec 24 '08 at 18:12
-
1@Jon, yes, there is - but it is itself internal, so you'd have to use more reflection to get it ;-p But it is STATE_VISIBLE. – Marc Gravell Dec 24 '08 at 18:17
What I did is temporarily remove the button from its parent controls to check its Visible value and then re-add to the parent controls.
If you need you can track the child index to re-add it at the right index.

- 73
- 5
I have same issue with classes derived from 'ToolStripItem' base class. so I used Available property value to check if item will be displayed or not. problem solved. Sample:
ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();
In this sample 'curItm' is an instance of of ToolStripItem derived class.
This problem with Visible/Enabled properties in .Net controls that depend on parent container's Visible/Enabled must be solved by .Net team. I create a costume property named IsVisible/IsEnabled in my own classes that return assigned value for Visible/Enabled properties and not the value that depend on parent container.

- 39
- 4
An option that doesn't rely on reflection would be to recurse through the parents of the control hierarchy looking for one with Visible set to false.
EDIT: See comments for significance of code.
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);

- 1,351
- 8
- 14
-
But that doesn't tell you whether the original is true or false; if there are no invisible parents, you can (probably) trust .Visible, but if there *are*, you have no clue whether your control has (locally) Visible=true or Visible=false – Marc Gravell Dec 24 '08 at 17:51
-
You would have to look at both, so if currently visible finding any parent that is false would mean it isn't currently. – toad Dec 24 '08 at 18:03
-
But Visible will never return true if any parent is invisible; that is the problem: the framework already checks this. I think the OP wants to know whether the control *locally* thinks it is visible, i.e. if all parents were visible, would it be too? You can't find this just by Visible. – Marc Gravell Dec 24 '08 at 18:06
-
Interesting, was not seeing it change because I was basing it off of the VisibleChanged event which was not firing when the parent controls visible property was changing. – toad Dec 24 '08 at 18:27
-
Guess this is a leaky abstraction, will edit post to put some code showing what I mean. When the parent is hidden a childs VisibleChanged is not fired, but when the parent is made Visible it is. – toad Dec 24 '08 at 18:33