在WrapPanel上垂直列出项目并利用多个列

时间:2012-07-05 13:04:25

标签: wpf silverlight xaml scrollviewer wrappanel

我需要垂直列出项目(全部大小相同)(使用ScrollViewer)。如果容器足够大以显示 x 列,我希望项目通过 x 列传播

我首先尝试过:

<ScrollViewer>
    <toolkit:WrapPanel Orientation="Horizontal" ItemHeight="30" ItemWidth="100">
        <Button Content="1" />
        <Button Content="2" />
        <Button Content="3" />
        <Button Content="4" />
        <Button Content="5" />
    </toolkit:WrapPanel>
</ScrollViewer>

结果 - WrapPanel的工作方式与我想的一样,但我的商品是从“从左到右”排序的(不是垂直的

然后我尝试将WrapPanel的Orientation设置为“ Vertical ”:

结果 - 我的商品是垂直排序的,但未在多列上展开。

以下是我要渲染项目的方式:

我真的想避免编写监控控件大小的代码来创建/删除列,具体取决于它的大小。

5 个答案:

答案 0 :(得分:9)

如果您将Orientation设置为Vertical,则还应设置渲染高度。例如WrapPanelHeight="150"

答案 1 :(得分:3)

最后得到的东西有效,但它需要代码。当你说我们需要调整WrapPanel的高度以使其有效时,我同意你们所有人的意见。这是我的解决方案:

<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>

这是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);

}

答案 2 :(得分:2)

WrapPanel没有定义Height

,这种行为是不可能的

您可以使用的一个替代方案是Grid,其中在OnLoadedOnSizeChanged中,它会计算适合的列数,然后设置网格的行/列定义以及代码隐藏中每个对象的Grid.Row / Grid.Column。它并不漂亮,但它应该相当简单,并且可以工作。

另一个选项是创建自己的自定义面板,根据需要排列项目。你甚至可以在网上找到已经可以做到的东西

答案 3 :(得分:1)

使用WrapPanel执行此操作的唯一方法是明确设置Height

看起来您希望项目在列上均匀分布,左列最多只有一列而不是右侧的列。如果这是您正在寻找的,那么您将需要创建自己的自定义面板。看看this,看看如何开始。您需要ItemWidth和ItemHeight依赖项属性,并使用ItemWidth和可用宽度计算可以拥有的列数。

答案 4 :(得分:0)

禁用垂直滚动条。这告诉WPF使用水平空间。

Frode,请尝试以下操作(VS2017 .NET 4.7.2):

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WpfApp1.MainWindow" Title="Wrap Panel Test" Height="100" Width="250">
    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Disabled">
        <WrapPanel Orientation="Vertical">
            <Button Width="100" Content="1" />
            <Button Width="100" Content="2" />
            <Button Width="100" Content="3" />
            <Button Width="100" Content="4" />
            <Button Width="100" Content="5" />
        </WrapPanel>
    </ScrollViewer>
</Window>

Wrap Panel Demo