List Items Vertically on a WrapPanel and take advantage of multiple columns List Items Vertically on a WrapPanel and take advantage of multiple columns wpf wpf

List Items Vertically on a WrapPanel and take advantage of multiple columns


If you set Orientation to Vertical you should also set render height. For example to WrapPanel, Height="150".


Finally got something that works but it needs code. I agree with all of you when you say that we need to resize height of the WrapPanel to make that works. Here is my solution :

<ScrollViewer x:Name="scroll1" SizeChanged="ScrollViewer_SizeChanged" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">    <toolkit:WrapPanel x:Name="wp1" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" ItemHeight="30" ItemWidth="250" >        <Button Content="1" />        <Button Content="2" />        <Button Content="3" />        <Button Content="4" />        <Button Content="5" />        <Button Content="6" />        <Button Content="7" />        <Button Content="8" />    </toolkit:WrapPanel></ScrollViewer>

Here is the CodeBehind :

private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e){    // Stupid magical number because ViewPortHeight is sometimes not accurate    Double MAGICALNUMBER = 2;    // Ensure ViewPortSize is not 0    if (scroll1.ViewportWidth <= MAGICALNUMBER || scroll1.ViewportHeight <= MAGICALNUMBER)        return;    Size contentSize = new Size(scroll1.ViewportWidth - MAGICALNUMBER, scroll1.ViewportHeight - MAGICALNUMBER);    Size itemSize = new Size(wp1.ItemWidth, wp1.ItemHeight);    Size newSize = CalculateSizeBasedOnContent(contentSize, wp1.Children.Count, itemSize);    wp1.Width = newSize.Width;    wp1.Height = newSize.Height;}private Size CalculateSizeBasedOnContent(Size containerSize, int itemsCount, Size itemSize){    int iPossibleColumns = (int)Math.Floor(containerSize.Width / itemSize.Width);    int iPossibleRows = (int)Math.Floor(containerSize.Height / itemSize.Height);    // If all items can fit in first column without scrolling (or if container is narrow than the itemWidth)    if (itemsCount <= iPossibleRows || containerSize.Width < itemSize.Width)    return new Size(itemSize.Width, (itemsCount * itemSize.Height));    // If all items can fit in columns without scrollbar    if (iPossibleColumns * iPossibleRows > itemsCount)    {    int columnsNeededForDisplay = (int)Math.Ceiling((itemsCount/(Double) iPossibleRows));    return new Size(columnsNeededForDisplay * itemSize.Width, containerSize.Height);    }    // Here scrolling is needed even after spreading in columns    int itemsPerColumn = (int)Math.Ceiling(wp1.Children.Count / (Double)iPossibleColumns);    return new Size(containerSize.Width, itemsPerColumn * itemSize.Height);}


That sort of behavior is not possible with a WrapPanel without defining its Height

One alternative you could use is a Grid, where in OnLoaded and OnSizeChanged, it calculates how many columns will fit, then sets the Row/Column definitions of the Grid and the Grid.Row/Grid.Column of each object in the code-behind. It's not pretty, but it should be fairly simple to put together and will work.

The other option would be creating your own Custom Panel that arranges the items how you want. You might even be able to find something available online that already does that