WinUI 3 ItemsView with LinedFlowLayout items shrinking instead of wrapping

I have an ItemsView control with LinedFlowLayout inside my WinUI 3 application. I would like to make a list of "tags", but for some reason I cannot figure out, when the window is resized instead of wrapping whenever there isn't enough space in the line the items start shrinking by a little before actually wrapping.
Page xaml:
<ItemsView Grid.Row="1" ItemsSource="{x:Bind ViewModel.Tags}">
<ItemsView.ItemTemplate>
<DataTemplate x:DataType="local:Tag">
<ItemContainer>
<Border BorderThickness="1" BorderBrush="Black" CornerRadius="12" Padding="8,2">
<StackPanel Orientation="Horizontal" Spacing="4" Width="Auto">
<TextBlock Text="{x:Bind TagName}"/>
<AppBarSeparator/>
<TextBlock Text="{x:Bind WordCount}"/>
</StackPanel>
</Border>
</ItemContainer>
</DataTemplate>
</ItemsView.ItemTemplate>
<ItemsView.Layout>
<LinedFlowLayout LineSpacing="8" MinItemSpacing="8"/>
</ItemsView.Layout>
</ItemsView>
Here is how the "shrinking" looks like: Lined Flow Layout items shrinking
I have tried various changes to the data template items including reducing them to the bare minimum - a single text block. Also different collections, but none of the combinations yielded the desired result. I would like for my items to just wrap to the next line whenever they are out of space instead of shrinking.
Answer
You're seeing tags shrink slightly before wrapping because of the default behavior of LinedFlowLayout
, which attempts to fit more items on the current line by reducing their size, unless you explicitly disable this behavior.
By default, LinedFlowLayout
uses a layout behavior that tries to compress items before wrapping them. This is similar to flex-shrink
in CSS flexbox. That’s why even though your tags look like they should wrap, they first “shrink a bit” as the container is resized.
Set the layout’s LayoutBehavior
to "Fill"
and ItemsStretch="None"
to disable the shrinking behavior.
<ItemsView.Layout>
<LinedFlowLayout
LineSpacing="8"
MinItemSpacing="8"
LayoutBehavior="Fill"
ItemsStretch="None"/>
</ItemsView.Layout>
And make sure your item container doesn’t implicitly stretch. Use HorizontalAlignment="Left"
:
<StackPanel Orientation="Horizontal" Spacing="4" HorizontalAlignment="Left">
<TextBlock Text="{x:Bind TagName}"/>
<AppBarSeparator/>
<TextBlock Text="{x:Bind WordCount}"/>
</StackPanel>
Full example
<ItemsView Grid.Row="1" ItemsSource="{x:Bind ViewModel.Tags}">
<ItemsView.ItemTemplate>
<DataTemplate x:DataType="local:Tag">
<ItemContainer>
<Border BorderThickness="1" BorderBrush="Black" CornerRadius="12" Padding="8,2">
<StackPanel Orientation="Horizontal" Spacing="4" HorizontalAlignment="Left">
<TextBlock Text="{x:Bind TagName}"/>
<AppBarSeparator/>
<TextBlock Text="{x:Bind WordCount}"/>
</StackPanel>
</Border>
</ItemContainer>
</DataTemplate>
</ItemsView.ItemTemplate>
<ItemsView.Layout>
<LinedFlowLayout
LineSpacing="8"
MinItemSpacing="8"
LayoutBehavior="Fill"
ItemsStretch="None"/>
</ItemsView.Layout>
</ItemsView>
More info:
Official LinedFlowLayout docs – Microsoft Learn
LayoutBehavior="Fill"
makes the layout allocate items based on their desired size rather than compressing them to fit more in a line.GitHub issue confirming shrink-before-wrap: WinUI #6643
Items shrink because the default stretch mode isn't set to
None
.Related flex-wrap behavior in CSS (same underlying layout model concepts apply)
Use LayoutBehavior="Fill"
and ItemsStretch="None"
on LinedFlowLayout
to stop items from shrinking. Also make sure your item containers aren’t set to stretch. That’s it.
Enjoyed this question?
Check out more content on our blog or follow us on social media.
Browse more questions