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?
                +5 
                A: 
                
                
              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 });
                  Marc Gravell
                   2008-12-24 17:36:09
                
              Thanks, I'll vote up after waiting for more answers.
                  Qwertie
                   2008-12-24 18:00:07
                What is the 2? Is there a constant or enum you can use instead?
                  Jon B
                   2008-12-24 18:12:13
                @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
                   2008-12-24 18:17:02
                @Qwertie; up-votes don't usually detract answers; marking as answered might, but to be honest I'm pretty sure there isn't a more elegant way to do this...
                  Marc Gravell
                   2008-12-24 18:18:31
                This is for win forms, do you know if this is also the only way to obtain the "local" visible within asp.net forms as well?
                  Robin Day
                   2010-01-04 16:22:48
                Sorry, no I don't. You might have to walk upwards.
                  Marc Gravell
                   2010-01-04 16:30:15
                
                
                A: 
                
                
              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);
                  Jeremy Wilde
                   2008-12-24 17:48:55
                
              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
                   2008-12-24 17:51:08
                You would have to look at both, so if currently visible finding any parent that is false would mean it isn't currently.
                  Jeremy Wilde
                   2008-12-24 18:03:09
                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
                   2008-12-24 18:06:48
                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.
                  Jeremy Wilde
                   2008-12-24 18:27:47
                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.
                  Jeremy Wilde
                   2008-12-24 18:33:06