-
Notifications
You must be signed in to change notification settings - Fork 108
Fix WrapPanel stretching behavior for last item #704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix WrapPanel stretching behavior for last item #704
Conversation
Added a conditional check to prevent the last item in the WrapPanel from stretching when the parent measure's width is infinite.
Thanks Andrew, I think a screenshot would have helped me understand the context too. If I understand correctly, in the case where this is happening, all the items are going to be laid out on one row, as it'll never wrap due to the infinite available width, right? Therefore, yes it makes sense that the last item should just be whatever size it wants vs. trying to fill that void. Is there a case where that wouldn't be true? Even if in the measure pass it's infinite and doesn't stretch, if the arrange pass is fixed, then it should self-correct and still stretch when laying out, right? It could be good to add a test here too just to catch this case so we can ensure we don't regress if we modify this logic in the future. Thanks for taking a look into this! 🦙❤️ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a WrapPanel stretching behavior issue where the last item would attempt to stretch to infinite width when the parent container provides infinite measure constraints, causing a System.Runtime.InteropServices.COMException.
- Added a conditional check to prevent stretching when parent measure width is infinite
- Resolves crashes in scenarios where WrapPanel is placed in auto-sized containers
@@ -219,7 +219,8 @@ void Arrange(UIElement child, bool isLast = false) | |||
} | |||
|
|||
// Stretch the last item to fill the available space | |||
if (isLast) | |||
// if the parent measure is not infinite | |||
if (isLast && double.IsInfinity(parentMeasure.U) is false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Using 'is false' pattern is less readable than the negation operator. Consider using '!double.IsInfinity(parentMeasure.U)' for better readability and consistency with common C# practices.
if (isLast && double.IsInfinity(parentMeasure.U) is false) | |
if (isLast && !double.IsInfinity(parentMeasure.U)) |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I accidentally hit this button... interesting.
See #1961 for details.
Hi @michael-hawker. Thanks for the feedback. 🙂
This PR just skips the last item stretching if the given space, width or height depending on the
Yes. The UpdateRows() method is also called on arrange.
I'm working on this. |
@michael-hawker I added a simple test case, and it passes successfully with the fix. Without the fix, the test doesn't technically "fail". It breaks the test host itself. This is the error I'm getting:
I already tried handling this at App.xaml but didn't help. public App()
{
this.InitializeComponent();
UnhandledException += (sender, e) =>
{
// Confimed that the exception (System.Runtime.InteropServices.COMException)
// is handled.
e.Handled = true;
};
} I don't think that this behavior is related to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @AndrewKeepCoding, I see you use the term "infinite width", but *
does not mean "infinite". It means "stretch, using equal space" and that can be seen by something like <Grid ColumnDefinitions="1*, 3*">
. This means: the second column must be three times the size of the first. In other words: two columns, 25% and 75% width of the total. When you have only one column, and one child element, that means the Grid is stretched horizontally, so the child is actually correctly stretching its last item.
Notes: Auto means the minimum size needed (determined by the children) and notice the pretty rounded corners on the right hand side? Nothing is being clipped.
Hi @Jay-o-Way! Thanks for the clarification 🙂 By “infinite width,” I’m specifically referring to the availableSize.Width argument passed to the WrapPanel’s MeasureOverride() method. In some layouts, such as when the panel is placed inside a Grid with Auto column width, this value can be double.Infinity. When that happens, the last item tries to stretch across an infinite space, which leads to a System.Runtime.InteropServices.COMException. This PR introduces a guard to skip that stretching behavior when infinite space is detected. Sorry for the confusion. |
@AndrewKeepCoding yep, you know a lot more about this than I do. <Grid ColumnDefinitions="*">
<controls:WrapPanel StretchChild="Last"> combined with your first screenshot, the result IS exactly what I would expect it to be: the grid is stretched, and the last item stretches pretty inside the available space. The result you introduce with this PR is that the last element does not stretch, and that would seem like a new bug (for future developers who don't know about this history). Obviously, the runtime exception is something to solve, but I don't think this is the best result. |
As long a any control does not have a minimum size, that is to be expected. |
Since both |
Added a conditional check to prevent the last item in the WrapPanel from stretching when the parent measure's width is infinite.
Fixes
Fixes #703 and #297
PR Type
What kind of change does this PR introduce?
What is the current behavior?
THIS WORKS:
THIS THROWS:
This code tries to stretch its last item to an infinity width causing System.Runtime.InteropServices.COMException.
What is the new behavior?
Doesn't stretch its last item when given an infinity width.
PR Checklist
Please check if your PR fulfills the following requirements:
Other information