New row not created for last child in WrapPanel when StretchChild=Last
As I was writing up the spec for the WinUI transfer and looking at primitive examples and was a bit baffled at what was happening with StretchChild and my intuitive expectations...
Take this code:
<controls:WrapPanel Width="132" StretchChild="Last">
<Rectangle Fill="Red" Width="45" Height="44"/>
<Rectangle Fill="Blue" Width="44" Height="44"/>
<Rectangle Fill="Green" Width="44" Height="44"/>
<Rectangle Fill="Orange" Height="44"/>
</controls:WrapPanel>
This properly stretches the last item across the bottom:
However, if we make enough room for the green box on the first row (by making the red 44 width [only change])...
<controls:WrapPanel Width="132" StretchChild="Last">
<Rectangle Fill="Red" Width="44" Height="44"/>
<Rectangle Fill="Blue" Width="44" Height="44"/>
<Rectangle Fill="Green" Width="44" Height="44"/>
<Rectangle Fill="Orange" Height="44"/>
</controls:WrapPanel>
Actual: Then the Orange rect disappears entirely!
Expected: I would expect it to span the entire bottom row, like so:
This is the behavior we should at least make sure works, and have a test for. FYI @azchohfi as we'll need to port whatever fixes we make here to WinUI as well. I'm going to spec it up as I expect it to work for now.
Originally posted by @michael-hawker in https://github.com/CommunityToolkit/Windows/issues/704#issuecomment-3453843121
From PR Thread from @AndrewKeepCoding :
Not sure if this is the same or a different scenario, so would be good to discuss/confirm if it's the same or a different bug.
@michael-hawker I believe this is a different issue. We get this bug because the
WrapPaneldoesn't create a new row when the last child'sDesiredWidthis 0. In this case, we can check if theposition.Uis larger than theparentMeasure.U.I took a quick look and it seems that we can address this by updating the condition like so:
void Arrange(UIElement child, bool isLast = false) { ... var desiredMeasure = new UvMeasure(Orientation, child.DesiredSize); -- if ((desiredMeasure.U + position.U + paddingEnd.U) > parentMeasure.U) ++ if ((desiredMeasure.U + position.U + paddingEnd.U) > parentMeasure.U || position.U >= parentMeasure.U) { // next row! position.U = paddingStart.U; position.V += currentRow.Size.V + spacingMeasure.V; _rows.Add(currentRow); currentRow = new Row(new List<UvRect>(), default); } ... }Let me know if you want me to create a new issue for this one.
@michael-hawker I'm happy to work on a PR for this given the green light. 🙂
Thanks @AndrewKeepCoding much appreciate all your support! 🦙❤️ It'd be great to have a few of these mini little easy to parse samples in the tests for checking we're consistent on the behavior for the future. I've assigned to you for tracking.
Once we get your other PR and this one merged in (@Arlodotexe want to take a look?); I can investigate how we update the ported WinUI version with the proper fixes.