3

I am working on a custom control that has a custom panel and inside the custom panel I have a small and simple MeasureOverride method that passes the size of double.PositiveInfinity to its children MeasureOverride method. The custom panel should take care of the layout and it should make children bigger or smaller depending on window size.

If you have dealt with controls you should then know how wpf layout system works and that basically every child calls MeasureOverride which calls MeasureOverride of childs children and so on.

Now the problem is that when I resize the window, the custom panel does get receive the flag to do the measure again hence the MeasureOverride does get called again but this time while passing the double.PositiveInfitinty size to its children, the children MeasureOverride doesn't get called at all (but the method should be called according to the definition of WPF layout system). Why is that so? I always thought when I call the MeasureOverride on a parent that it children will also be forced to do the measure.

Obviously I am wrong so could somebody explain me how does a control/child know when to measure again?

By the way I am passing the size of double.PositiveInfinity to the children to tell them to take as much space as needed.

Code:

protected override Size MeasureOverride(Size availableSize)
{
 double x;
 double y;
 var children = this.InternalChildren;
 for (int i = 0; i < children.Count; i++)
     {
       UIElement child = children[i];
       child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity);
       y += child.DesiredSize.Height;
       x = Math.Max(x, child.DesiredSize.Width);
      }
 return new Size(x, y);
}

Code is simple. I dont get it why the children doesnt get measured again. And sorry if i have misspelled something in code.

cyberist
  • 107
  • 1
  • 10

2 Answers2

3

Your children won't get measured again because they don't have to: since you keep passing the same size, WPF knows that there is no reason to measure again since the resulting DesiredSize will be the same.

That being said, the Desiredsize updated by Measure is only the size that your child considers the most appropriate. You should take it into account when overriding ArrangeOverride, but you have no obligation to: simply arrange your children the way you like, the fact that MeasureOverride is called or not for your children should be irrelevant.

Julien Lebosquain
  • 40,639
  • 8
  • 105
  • 117
  • Does that mean they will never be measured again since I will be always passing them double.PositiveInfinity? I need to call them to measure. When the window has changed the size, each child needs to be measured because the children have specific measure logic. – cyberist Feb 08 '13 at 16:09
  • 1
    Then you should measure the element with the given constraint or you need to somehow notify the elements of the size change and invalidate their measure. Note of course that invalidating the measure just dirties that element and not any of its descendants or its ancestors so if you're relying on the DesiredSize to change then you'll need to walk up the element tree and invalidate all the measures up to your panel which makes a pretty tight coupling between those children and the panel. – AndrewS Feb 08 '13 at 18:43
  • lets say my panel has 300x300 and then i change the width size of one child to 400. how can i tell my panel to invalidate the panel if the with of child > 300 as in this case? – cyberist Feb 08 '13 at 21:16
  • @AndrewS can you help me how to tell parents to fit to the size of children? – cyberist Feb 09 '13 at 10:06
  • @cyberist: What are you really trying to accomplish? Don't pass PositiveInfinity if your children must be constrained to a specific size: pass the available size and your children will get measured again. – Julien Lebosquain Feb 09 '13 at 10:56
  • I trigger update measure on any child and I want the parent to also measures again. – cyberist Feb 09 '13 at 16:16
  • 1
    @cyberist A child doesn't tell a parent how it should size/measure/arrange it. A parent will measure the child with some constraint - typically either with the infinity or with some portion of the constraint it was given. A parent then typically (but not always) uses the DesiredSize of that element when arranging it. If something happens that invalidates the measure of that child later it will be remeasured with the same constraint it was measured with last. If what it returns is different than last time then the OnDesiredSizeChanged of the parent is called and its measure is invalidated. – AndrewS Feb 11 '13 at 15:47
  • That may then mean that that element will return a different size for its DesiredSize so its parent may get invalidated. And it goes on up the tree unless it stops along the way. – AndrewS Feb 11 '13 at 15:48
  • How does the parent know when is child desizeSize changed? – cyberist Feb 11 '13 at 16:42
0

Have you tried calling the UIElement.InvalidateMeasure where UIElement is your parent panel?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
sacha barber
  • 2,214
  • 1
  • 24
  • 37