But I *did* set the properties! (or, the Invisible Visible Controls)



  •  C# WinForms app, trying to set some properties... 

    lblCore.Visible = component.CoreLevel != null;
    lblCore.Text = "Is a level " + component.CoreLevel + " core component.";
    (snip more controls being set)
    // HACK - can't check the visible properties, they're magically not set yet, WTF? pnlMiscellaneous.Visible = component.CoreLevel != null || component.CommandAndControl != 0 || component.EnergyStorage != 0 || component.Power != 0 || component.Torque != 0 || component.Thrust != null;

    So wait, what kind of magic is this? I can't just test whether the controls are visible, because despite my just now setting them visible a few lines above, their Visible properties are still set to false! Can't be a threading issue, because all this is happening on the UI thread (I hope). Is the call to set the Visible property not actually setting it, but instead storing a flag somewhere to set it on the next GUI refresh or something? There's nothing in the MSDN documentation to suggest that setting a control visible does not actually make it immediately visible, so WTF is going on here?



  •  That'd be my guess.  It's not just WinForms, either, I ran into the same problem a few weeks ago in my current big ASP.NET project.

     



  • In .net The "Visible" propery only gets set when the parent is also visible, I mean, If I have a Control which is not visible and inside I place another control which is visible the inner control will not be set to visible unless the parent is set to visible too which, in my opinion, is normal because you can not show something which is inside an invisble control...



  • @Khalin said:

    In .net The "Visible" propery only gets set when the parent is also visible, I mean, If I have a Control which is not visible and inside I place another control which is visible the inner control will not be set to visible unless the parent is set to visible too which, in my opinion, is normal because you can not show something which is inside an invisble control...

    That means that you can't have invisible controls inside invisible controls, stay invisible, if the outer control becomes visible. That doesn't seem normal to me... Now, I hastily add that I'm not adept at either WinForms or .net, so I may be missing some of the picture here.



  • Kind of. It means that if you try to make a control visible inside an invisible control it will have no effect (which as far as I can understand follows centain logic). if you really want to make it visible the parent MUST be visible.... is like if you want to show something that is inside a box but the box is hidden to the people



  • @Khalin said:

    Kind of. It means that if you try to make a control visible inside an invisible control it will have no effect (which as far as I can understand follows centain logic). if you really want to make it visible the parent MUST be visible.... is like if you want to show something that is inside a box but the box is hidden to the people

    I understand where you're coming from all right. Consider, however, a visible control with controls in it, some of which are visible, some of which aren't. Let's assume that this is intentional. Then you make the outer control invisible, rendering the controls inside invisible. Next, you make the outer control visible again. Then what?



  • Then the controls which were invisible will remain invisible and the controls which were visible will remain visible (I haven't tried it for long but that's what I think that happened the last time I tried something similiar). I think the point is that you can't change the visibility of the child controls if the parent is hidden



  • @Khalin said:

    Then the controls which were invisible will remain invisible and the controls which were visible will remain visible (I haven't tried it for long but that's what I think that happened the last time I tried something similiar). I think the point is that you can't change the visibility of the child controls if the parent is hidden
     

    So, MS wants to put two different pieces of info into a single boolean.



  • @Mcoder said:

    @Khalin said:

    Then the controls which were invisible will remain invisible and the controls which were visible will remain visible (I haven't tried it for long but that's what I think that happened the last time I tried something similiar). I think the point is that you can't change the visibility of the child controls if the parent is hidden
     

    So, MS wants to put two different pieces of info into a single boolean.

    No, you're looking at it the wrong way.

    Control.set_Visible(bool value) is setting the visibility flag, which I believe calls ShowWindow(hWnd, (BOOL)value) on the underlying window. This won't make the control visible if its parent is invisible, but it will set the flag, so that if the parent becomes visible, so will this one.

    Control.get_Visible(), on the other hand, asks the question "is this control visible?" If the control itself is marked invisible, then that's easy. If it's visible, though, it needs to check the parent, and the parent's parent, etc, to determine visibility. If one of those is not visible, then it stands to reason that this control can't be visible either.



  • Still, that means there's an internal "isVisible" flag or somesuch that I can't access, and I have to guess at or store on my own!



  • Note that Win32, upon which Winforms runs, behaves exactly the same way.

    It seems to me that using the Visibility of a control to determine other business logic is the wrong way to approach it. You should use the logic you use to determine the visibility of first window. That way, some other jerk calling ShowWindow() can't corrupt your state, only your GUI.



  • @pkmnfrk said:

    @Mcoder said:

    @Khalin said:

    Then the controls which were invisible will remain invisible and the controls which were visible will remain visible (I haven't tried it for long but that's what I think that happened the last time I tried something similiar). I think the point is that you can't change the visibility of the child controls if the parent is hidden
     

    So, MS wants to put two different pieces of info into a single boolean.

    No, you're looking at it the wrong way.

    Control.set_Visible(bool value) is setting the visibility flag, which I believe calls ShowWindow(hWnd, (BOOL)value) on the underlying window. This won't make the control visible if its parent is invisible, but it will set the flag, so that if the parent becomes visible, so will this one.

    Control.get_Visible(), on the other hand, asks the question "is this control visible?" If the control itself is marked invisible, then that's easy. If it's visible, though, it needs to check the parent, and the parent's parent, etc, to determine visibility. If one of those is not visible, then it stands to reason that this control can't be visible either.

    Finally someone who understands what I tried to mean and can explain it better than I do! hahaha That's the problem when I try to explain something in English (which is not my usual language)


  • @ekolis said:

    Still, that means there's an internal "isVisible" flag or somesuch that I can't access, and I have to guess at or store on my own!

    If you're asking if a control is visible, you're asking, "hey, can the user see this control?" If the parent is invisible, then the answer is no. Because duh. The control isn't visible. That's a different question from, "hey if I made the parent to this control visible, would this control be visible?" which I believe as you imply you have to write your own code to handle. Not only does it make perfectly good sense to me, I can't even envision how or why you'd implement it any differently.

    Imagine the confusion if it didn't work that way. "It says this control is visible, but I'm not seeing it! THIS IS SO OBVIOUSLY BUGGY!"


  • Considered Harmful

    These are two separate pieces of information and both should be accessible somehow. I also expect the getter from a property I just set, to return the (possibly normalized) value I just set it to.

    This is something akin to DOM's .getComputedStyle() being separate from .style.



  •  More partial info, in case it helps any: My particular problem involved placeholder objects. There wasn't an issue with them being inside another hidden object. Not sure exactly when the problem does/doesn't arise, I've just been coding defensively against the possibility since it first came up.

     



  • @joe.edwards said:

    These are two separate pieces of information and both should be accessible somehow. I also expect the getter from a property I just set, to return the (possibly normalized) value I just set it to.
    Then you don't understand properties very well.

    It's like having 2 classes, one private and one public (inside the private class). 

    private class Outer

    {

       public Inner { get; set; }

    }

    Just because the inner class is public doesn't mean I can get to it, because I can't access the object that contains it.



  • @pkmnfrk said:

    Control.set_Visible(bool value) is setting the visibility flag, which I believe calls ShowWindow(hWnd, (BOOL)value) on the underlying window. This won't make the control visible if its parent is invisible, but it will set the flag, so that if the parent becomes visible, so will this one.

    Control.get_Visible(), on the other hand, asks the question "is this control visible?" If the control itself is marked invisible, then that's easy. If it's visible, though, it needs to check the parent, and the parent's parent, etc, to determine visibility. If one of those is not visible, then it stands to reason that this control can't be visible either.

    For me, it might be less confusing if set_Visible and get_Visible were each other's exact "opposites". There might be an is_Visible for what's now get_Visible, and get_Visible would return the value of the actual flag. Because it might be relevant for a developer to know, if a visibility flag is set, regardless of whether or not the control is actually visible.



  • @joe.edwards said:

    These are two separate pieces of information and both should be accessible somehow. I also expect the getter from a property I just set, to return the (possibly normalized) value I just set it to.

    Possibly, but:

    1) The one named "Visible" should behave as it does now, so that behavior shouldn't be a surprise

    2) You probably shouldn't bother dinking around with visibility anyway until the parent object becomes visible, then do your shit. Like populating menus, you do it when you need to display the menu, not way beforehand for no reason.

    @joe.edwards said:

    This is something akin to DOM's .getComputedStyle() being separate from .style.

    I hate .getComputedStyle(). I want to find the person who invented that and strangle them. What a over-complicated piece of bullshit. Microsoft's ".currentStyle" is ... 99999 times better, so of course that's not the method the W3C chose, they chose the fucking retarded method which requires (when used on arbitrary styles) you to create a look-up table for a style's CSS name (margin-right) to its JS/DOM name (marginRight). God I hate the W3C. Hate hate hate.


  • Considered Harmful

    @Sutherlands said:

    @joe.edwards said:

    These are two separate pieces of information and both should be accessible somehow. I also expect the getter from a property I just set, to return the (possibly normalized) value I just set it to.
    Then you don't understand properties very well.

    It's like having 2 classes, one private and one public (inside the private class). 

    private class Outer

    {

       public Inner { get; set; }

    }

    Just because the inner class is public doesn't mean I can get to it, because I can't access the object that contains it.

    This has nothing to do with member visibility.

    What I was saying is that the contract of a getter is symmetrical to the contract of a setter. The getter should return at least an equivalent representation of the value it was set to. If you set the value of the property and it couldn't be set for some reason (not actually the case here), then an exception should signal that the operation failed. If (as in this case) the getter is accessing an entirely different datum than the setter is setting, then the contract is incorrect and there should be a different getter to access the computed value (as shown in my analogy with DOM). Again, member visibility has nothing to do with it.

    If you're saying the value we're setting here SHOULD be encapsulated and hidden away once set, then this is still the wrong way to approach it.



  • You guys are way over-thinking this. You're asking, "is this control visible?" It's it's not drawn on the screen, then it's not visible. Period.


  • Considered Harmful

    The value you are setting is the "I want this to be what happens", so the symmetrical question is "what do I want to happen?" "What happened?" is a different question, so something like getComputedStyle is appropriate.

    If Visible is meant to reflect live values, then it should be read-only, and another property should exist for "IWantThisToBeVisible" (but better-named).



  • @ekolis said:

    Still, that means there's an internal "isVisible" flag or somesuch that I can't access, and I have to guess at or store on my own!

    No, it means that while the property of an element might be visible, it migh tnot actually be shown based off of it's parents settings.
    If a control is not visible you don't have to check higher.
    If a control is visible, then check it's parent and on up the stack. If all parents are visible then the control is visible, if any parent is not visible then the final state is not visible.
    It isn't an extra property, it's a property mix of all pareants, somthing like:

    If me.visible and me.parent.visible and me.parent.parent.visible (etc...) then I am visible.



  • @blakeyrat said:

    You guys are way over-thinking this.

    A lot of people have told me I over-think things in my yet-short life. I know you're being general and not talking to me specifically, and I'm willing to give you the benefit of the doubt, but 95% of those people were complete and utter morons. The other 5% were (mostly) very interesting people.



  • @KattMan said:

    @ekolis said:
    Still, that means there's an internal "isVisible" flag or somesuch that I can't access, and I have to guess at or store on my own!

    I agree. This are two different things.

    @KattMan said:

    No, it means that while the property of an element might be visible, it migh tnot actually be shown based off of it's parents settings.
    If a control is not visible you don't have to check higher.
    If a control is visible, then check it's parent and on up the stack. If all parents are visible then the control is visible, if any parent is not visible then the final state is not visible.
    It isn't an extra property, it's a property mix of all pareants, somthing like:

    If me.visible and me.parent.visible and me.parent.parent.visible (etc...) then I am visible.

    In Delphi VCL, Visible property affect only object component.

    To check if component is actually shown there is read-only Showing property. it will be false if any of parents have Visible == false.

    This solution is clear and logical.



  • I agree with blakeyrat. When you set a property it means that you want to do something with it, it's not like "I want to set it for the future". The Visible property means that you want the control to be visible or not. It's like real life. Taking again the example of the box. if you want to show the item inside the box you MUST show the box first and the you CAN show the item inside the box, never before. MS is doing the right thing in here. if the control is not visible then the property need to return false because doesn't matter how you look at it, the control is NOT visible


  • ♿ (Parody)

    @Khalin said:

    I agree with blakeyrat. When you set a property it means that you want to do something with it, it's not like "I want to set it for the future". The Visible property means that you want the control to be visible or not. It's like real life. Taking again the example of the box. if you want to show the item inside the box you MUST show the box first and the you CAN show the item inside the box, never before. MS is doing the right thing in here. if the control is not visible then the property need to return false because doesn't matter how you look at it, the control is NOT visible

    But then, if you can call setVisible(true) (without getting an exception) when the parent isn't visible, by this logic, shouldn't that force the parent to suddenly become visible? The issue here is that something is exposed that looks like simple setters / getters, but is really a lot more complex, and so is easy to confuse.

    As others have pointed out, there are two bits of information here: 1) is this widget actually being shown in the UI and 2) should this widget be visible when its parent is being shown in the UI. There are legitimate arguments on both sides, and both are going to confuse people. I think the Delphi way of dealing with this is pretty sensible.



  • @Khalin said:

    I agree with blakeyrat. When you set a property it means that you want to do something with it, it's not like "I want to set it for the future". The Visible property means that you want the control to be visible or not. It's like real life. Taking again the example of the box. if you want to show the item inside the box you MUST show the box first and the you CAN show the item inside the box, never before. MS is doing the right thing in here. if the control is not visible then the property need to return false because doesn't matter how you look at it, the control is NOT visible

    Guess you're right.

    Blakey, sorry for being all pissy, I overreacted; it's a pet peeve of mine. Not your fault. Used to work a lot of jobs with a lot of morons before I started programmig professionally...



  • @boomzilla said:

    @Khalin said:
    I agree with blakeyrat. When you set a property it means that you want to do something with it, it's not like "I want to set it for the future". The Visible property means that you want the control to be visible or not. It's like real life. Taking again the example of the box. if you want to show the item inside the box you MUST show the box first and the you CAN show the item inside the box, never before. MS is doing the right thing in here. if the control is not visible then the property need to return false because doesn't matter how you look at it, the control is NOT visible

    But then, if you can call setVisible(true) (without getting an exception) when the parent isn't visible, by this logic, shouldn't that force the parent to suddenly become visible? The issue here is that something is exposed that looks like simple setters / getters, but is really a lot more complex, and so is easy to confuse.

    As others have pointed out, there are two bits of information here: 1) is this widget actually being shown in the UI and 2) should this widget be visible when its parent is being shown in the UI. There are legitimate arguments on both sides, and both are going to confuse people. I think the Delphi way of dealing with this is pretty sensible.

    Well.. I think that depends on the point of view. In .Net the properties are fields which can include code in setters/getters which means they are "unpredictable". I think I need to explain that. with unpredictable I mean that the setter/getter method can depend on the context (that's the case I think we are dealing with). In my opinion a child cannot be visible and cannot force the parent to be visible. Same case happens with the DOM (taking one example said above), if you have a hidden DIV which contains another hidden DIV, the parent will now be set to visible when you set the child to visible, and the child will not be set to visible when you set the parent to be visible. probably there should be another property which says if the control has the Visible field set to true/false but as i said, it's a property, not a field...



  • @pkmnfrk said:

    Note that Win32, upon which Winforms runs, behaves exactly the same way.

    In Win32 API you can at least call GetWindowLong with GWL_STYLE and use some bit checking to get whether the window is marked to be visible if the parent is visible (used this more than once...). In .NET you either have to use PInvoke or store the visible flag at an additional position if your logic needs it...


  • Considered Harmful

    @Khalin said:

    In .Net the properties are fields which can include code in setters/getters which means they are "unpredictable". I think I need to explain that. with unpredictable I mean that the setter/getter method can depend on the context (that's the case I think we are dealing with).

    They're predictable by convention. There's nothing in the language preventing a setter from setting a completely different value than the getter reads, except that that is a retarded and confusing way to design a contract. Doing this breaks the (quite reasonable) assumption that the property will both read from and write to the same place. Even if this is not actually true, it's the onus of the designer of the interface to ensure that it appears to behave this way.

    If the contract breaks the reasonable expectations of its users, then it is a leaky abstraction.



  • So maybe "visible" isn't exactly the best name for it. But "WillBeDrawnIfItHasTheOpportunity" is a bit verbose, don't you think?


  • Considered Harmful

    I'll also note that this value cannot round-trip. Naive serialization of properties would fail to preserve the state of this object.

    c.Visible = c.Visible actually has side-effects here, setting the top-secret user-assigned-visibility value to the current computed value of the property. (By top secret I mean there is no way to read this value once it's been set.)


Log in to reply