C# UserControl Visible Property Not Changing

Debug.WriteLine(ucFollow.Visible);
ucFollow.Visible = true;
Debug.WriteLine(ucFollow.Visible);

ucFollow is a custom UserControl, nothing fancy. The above code prints out:

False
False

Worst part is, this does toggle the actual visibility of the UserControl (i.e. ucFollow does appear once this code is called), but it seems somehow that the Visible property isn't ... well, visible on the backend, and doesn't reflect the change, even though the UI itself does.

I don't even know where to begin troubleshooting this. Does anyone have any ideas as to what could remotely cause this kind of craziness?

Edit: This is with a standard C# WinForm in Visual Studio 2010.

Answers


I didn't break C#! :)

Turns out the culprit was the Form.Visible property. Before Form.Visible is set to true, any and all controls on the form will be invisible (Visible = false) no matter what.

However, you can still set Visible properties - they just won't take effect until the Form.Visible property is set to true.

In other words, when I called ucFollow.Visible = true, my program was indeed registering it - however, at that point in the code, ucFollow's parent Form.Visible was still false. Therefore, both the Debugger and my print statements recognized, "Hey, this control's parent form is still not visible, so this control is not visible. Period."

As soon as the form was made visible, all the changes took effect and everything worked great.

Moral of the story: Don't rely on the Visibility properties of your controls unless the form containing them is already visible and running.


the culprit is that controls Visible property is actually a property ( with get; set;) and the set will assign to internal m_Visible member but the get will look through all parent controls and will only return true if all of them have m_Visible == true


This is the danger of assuming properties and fields are the same thing. They are of course very similar conceptually (that's the point) but they are emphatically not that same mechanically. Have a look at what ucFollow.Visible = true actually does:

protected virtual void SetVisibleCore(bool value)
{
    try
    {
        HandleCollector.SuspendCollect();
        if (this.GetVisibleCore() != value)
        {
            if (!value)
            {
                this.SelectNextIfFocused();
            }
            bool flag = false;
            if (this.GetTopLevel())
            {
                if (this.IsHandleCreated || value)
                {
                    SafeNativeMethods.ShowWindow(new HandleRef(this, this.Handle), value ? this.ShowParams : 0);
                }
            }
            else
            {
                if (this.IsHandleCreated || (value && this.parent != null && this.parent.Created))
                {
                    this.SetState(2, value);
                    flag = true;
                    try
                    {
                        if (value)
                        {
                            this.CreateControl();
                        }
                        SafeNativeMethods.SetWindowPos(new HandleRef(this.window, this.Handle), NativeMethods.NullHandleRef, 0, 0, 0, 0, 23 | (value ? 64 : 128));
                    }
                    catch
                    {
                        this.SetState(2, !value);
                        throw;
                    }
                }
            }
            if (this.GetVisibleCore() != value)
            {
                this.SetState(2, value);
                flag = true;
            }
            if (flag)
            {
                using (new LayoutTransaction(this.parent, this, PropertyNames.Visible))
                {
                    this.OnVisibleChanged(EventArgs.Empty);
                }
            }
            this.UpdateRoot();
        }
        else
        {
            if (this.GetState(2) || value || !this.IsHandleCreated || SafeNativeMethods.IsWindowVisible(new HandleRef(this, this.Handle)))
            {
                this.SetState(2, value);
                if (this.IsHandleCreated)
                {
                    SafeNativeMethods.SetWindowPos(new HandleRef(this.window, this.Handle), NativeMethods.NullHandleRef, 0, 0, 0, 0, 23 | (value ? 64 : 128));
                }
            }
        }
    }
    finally
    {
        HandleCollector.ResumeCollect();
    }
}

(Code courtesy of ILSpy.)

Your answer lies somewhere in that tormented maze of logic.


Need Your Help

C++ Data Member Alignment and Array Packing

c++ data-structures packing bit-packing

During a code review I've come across some code that defines a simple structure as follows:

Parsing Atom & RSS in Ruby/Rails?

ruby-on-rails ruby rss atom-feed

I'm looking for something that will let me parse Atom and RSS in Ruby and Rails. I've looked at the standard RSS library, but is there one library that will auto-detect whatever type of feed it is ...