我需要垂直列出项目(全部大小相同)(使用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 ”:
结果 - 我的商品是垂直排序的,但未在多列上展开。
以下是我要渲染项目的方式:
我真的想避免编写监控控件大小的代码来创建/删除列,具体取决于它的大小。
答案 0 :(得分:9)
如果您将Orientation
设置为Vertical
,则还应设置渲染高度。例如WrapPanel
,Height="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
,其中在OnLoaded
和OnSizeChanged
中,它会计算适合的列数,然后设置网格的行/列定义以及代码隐藏中每个对象的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>