C# UserControl Visible Property Not Changing
Asked Answered
L

3

20
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.

Lashondalashonde answered 22/6, 2012 at 17:22 Comment(16)
Is this WinForms, ASP.NET, something else?Quan
WinForms, sorry, should've specifiedLashondalashonde
Well if you broke C# I'm afriad you're going to have to fix it.Ancestry
What thread are you executing that statement on?Parliamentarianism
Is there a control hierarchy in play? Assigning visible to true doesn't necessarily indicate that the control is visible if it is contained by a parent that isn't visible.Cougar
I would start with using a debugger and stepping into the Visible property. Then, if this is not possible, I would register a VisibleChanged event handler and set a breakpoint inside and inspect the call stack.Richly
@DavidYaw - This is executed on a separate thread created by an EventHandler. It's located in a function called FormBeforeCall(), which is called using: this.UIThread(() => FormBeforeCall());Lashondalashonde
There could be many reasons to see this kind of behavior, I wouldn't jump straight to a c# bug conclusion. Please provide a simple reproducible example.Gley
@UweKeim - When I view the Visible property with the debugger, I get the same behavior - Visible is false both before and after that line of code.Lashondalashonde
@Gley - That was a bit tongue-in-cheek, it's probably something I'm doing wrong but I figured we could use a bit of levity on a Friday afternoon. ;)Lashondalashonde
@TheDramaLlama Sure, but put yourself in the place of another developer with similar problem in the future, how could they find the information here to help them with a title like that? :)Gley
Not that I know of; the ucFollow control is just placed like any other control smack dab in a Form.Lashondalashonde
@Gley Heh, true, good point. :)Lashondalashonde
@TheDramaLlama We will of course need a reproducible example though. We don't have your code base and can only make guesses.Gley
Is the form visible when you run this code (ie is this code running in the Form.Load event?). If the control isnt physically visible, it will return false until it is.Candler
@Candler - Stole my thunder! I'm about to post the solution below. :)Lashondalashonde
L
37

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.

Lashondalashonde answered 22/6, 2012 at 17:44 Comment(2)
If you'd like to find out if the control would be visible (if the parent control was visible), you can see my question here for the solutionCandler
you can mark this as an answer, its perfectly ok to do so. Another wierd and wonderful behaviour of controls visibility (in design mode) is when you have a UserControl that you dont declare in the InitializeComponent().. (for what ever reason)... if you open the form the Control isn't shown nor is it listed in the Properties dropdownlist of controls.Frit
P
11

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

Prehistoric answered 5/11, 2013 at 9:17 Comment(0)
B
4

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.

Brookbrooke answered 22/6, 2012 at 17:32 Comment(1)
I have a feeling my solution can be linked with something in the aforementioned maze of logic, but it's a Friday and I can't be bothered to find it. :)Lashondalashonde

© 2022 - 2024 — McMap. All rights reserved.