Debug.WriteLine(ucFollow.Visible);
ucFollow.Visible = true;
Debug.WriteLine(ucFollow.Visible);
ucFollow is a custom UserControl, nothing fancy. The
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.