Answered problem with ArrangeOverride

  • Wednesday, December 26, 2007 5:58 PM
     
     

    Here's a doozy I've recently come across:

    I have a custom panel and a UserControl that has several instances inside the custom panel.

    Both classes have ArrangeOverride implemented.

    In the panel, I tell the custom user control to arrange itself in a given size, but when ArrangeOverride in the user control is called, the size is different(bigger) than what the panel told it to arrange itself in. As far as I can tell, it is equal to the DesiredSize that the UserControl calculated during the Measure pass. 

    Why would the size change somewhere between panel and usercontrol?

All Replies

  • Wednesday, December 26, 2007 6:32 PM
     
     

    Put watches eveywhere, go step by step, and see what happens with the size properties. In the process you'll probably get what happens.

  • Wednesday, December 26, 2007 7:30 PM
     
     Answered

    Believe it or not, this behavior is by design.  When you arrange a child whose desired size is larger than the size of the arrange rect, you are actually setting a position and a "clipping rect" (rather than an "arrange rect") for the child element. 

     

    Specifically, your call to child.Arrange(arrangeRect) will lead to an ArrangeCore() on the child.  If the supplied arrange size is smaller than the element's desired size, ArrangeCore() will always arrange the element at its desired size (minus its margins) and then store the supplied arrange size (a.k.a., finalSize) for clipping purposes.  Later, when the element is rendered, it's GetLayoutClip() method will use this stored arrange size to determine a clipping geometry.

     

    If you really want your user control to be limited ("constrained") to a specific size, you must do that in MeasureOverride() by returning the appropriate "DesiredSize".  That is actually why the parameter of MeasureOverride() is named "constraint".

     

    Hope this helps!

  • Saturday, January 10, 2009 3:51 AM
     
     
    This behavior seems broken to me - it violates what should be a complete separation of the "measure" and "arrange" phases. Measuring a child's desired size should not require a constraint and should have no side effects.

    I am trying to implement a custom panel class, and this layout behavior is causing me all sorts of problems. Specifically, I'm trying to create a subclass of StackPanel that uses all of (but no more than) the available layout space and gives as much space as possible to the child elements that need it.

    In order to do this, I need to know the desired size of all of the children before I can compute how much space I give them. The problem is that I can't Measure them without giving them a constraint on their size (which of course, I don't yet know).

    Extremely frustrating. I haven't found a way to work around it yet.
  • Friday, May 01, 2009 6:30 PM
     
     

    I've been messing with the same ____ on Silverlight today. I think they have copy-pasted the arrangement code from WPF :(
    I was trying to layout child TextBlock with Arrange method and found that it won't work if there is no Measure call with the same size parameter. I tryed the same code on WPF - the same behavior.

    I agree with Mike that this behavoir is very strange. It forces to spread arrangement logic to measure method too.