I'm trying to write a custom Panel class for WPF, by overriding MeasureOverride and ArrangeOverride but, while it's mostly working I'm experiencing one strange problem I can't explain.
In particular, after I call Arrange on my child items in ArrangeOverride after figuring out what their sizes should be, they aren't sizing to the size I give to them, and appear to be sizing to the size passed to their Measure method inside MeasureOverride.
Am I missing something in how this system is supposed to work? My understanding is that calling Measure simply causes the child to evaluate its DesiredSize based on the supplied availableSize, and shouldn't affect its actual final size.
Here is my full code (the Panel, btw, is intended to arrange children in the most space-efficient manner, giving less space to rows that don't need it and splitting remaining space up evenly among the rest--it currently only supports vertical orientation but I plan on adding horizontal once I get it working properly):
protected override Size MeasureOverride( Size availableSize ) {
foreach ( UIElement child in Children )
child.Measure( availableSize );
return availableSize;
}
protected override System.Windows.Size ArrangeOverride( System.Windows.Size finalSize ) {
double extraSpace = 0.0;
var sortedChildren = Children.Cast<UIElement>().OrderBy<UIElement, double>( new Func<UIElement, double>( delegate( UIElement child ) {
return child.DesiredSize.Height;
} ) );
double remainingSpace = finalSize.Height;
double normalSpace = 0.0;
int remainingChildren = Children.Count;
foreach ( UIElement child in sortedChildren ) {
normalSpace = remainingSpace / remainingChildren;
if ( child.DesiredSize.Height < normalSpace ) // if == there would be no point continuing as there would be no remaining space
remainingSpace -= child.DesiredSize.Height;
else {
remainingSpace = 0;
break;
}
remainingChildren--;
}
extraSpace = remainingSpace / Children.Count;
double offset = 0.0;
foreach ( UIElement child in Children ) {
//child.Measure( new Size( finalSize.Width, normalSpace ) );
double value = Math.Min( child.DesiredSize.Height, normalSpace ) + extraSpace;
child.Arrange( new Rect( 0, offset, finalSize.Width, value ) );
offset += value;
}
return finalSize;
}