使用 WrapPanel 和 ScrollViewer 在 WPF 中提供多列列表框
Posted
技术标签:
【中文标题】使用 WrapPanel 和 ScrollViewer 在 WPF 中提供多列列表框【英文标题】:Using WrapPanel and ScrollViewer to give a multi-column Listbox in WPF 【发布时间】:2010-10-28 19:54:22 【问题描述】:我正在制作一个简单的 LOB 应用程序,它从 XML 文件加载数据并将其显示在带有几个按钮的列表中以供编辑。
在我的第一次尝试中,一切都很好,只是列表在一个长列中向下滚动。我希望将数据包装起来,以便在窗口底部开始第二列,依此类推——如果您调整窗口大小,数据应该相应地调整大小。
首先,我只是将 ListBox 放在 ScrollViewer 中。这没有任何区别。
然后,我在 ItemTemplate 中添加了 WrapPanel。在这一点上,我得到了一个水平的长行,但它从来没有换到第二行,尽管我设置了 ScrollViewer.HorizontalScrollbar=disabled。
我在各种博客和论坛上搜索了网络,但看不出建议和我的代码(包括在下面)之间的区别。任何提示将不胜感激。
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="My App" Height="300" Width="400"
FocusManager.FocusedElement="Binding ElementName=eventsList">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Row="0" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ListBox Name="eventsList">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</ScrollViewer>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center" Visibility="Collapsed">
<Button Name="action1Button" />
<Button Name="action2Button" />
<Button Name="action3Button" />
</StackPanel>
</Grid>
</Window>
【问题讨论】:
【参考方案1】:您似乎走在了正确的轨道上:将 ListBox 中的 ItemsPanelTemplate 替换为 WrapPanel,将 WrapPanel 的 Orientation 设置为 Vertical,并将 ScrollViewer.VerticalScrollBar 设置为 Disabled 应该是您需要做的所有事情。
这对我有用:
<Window x:Class="ScrollingWrapPanel.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Red"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Orange"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Yellow"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Green"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Blue"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Indigo"/>
</ListBoxItem>
<ListBoxItem>
<Rectangle Width="80" Height="80" Margin="10" Fill="Violet"/>
</ListBoxItem>
</ListBox>
</Grid>
</Window>
这应该会导致它垂直渲染一整列,换行,然后继续下一列,根据需要水平滚动(但不是垂直),如图所示:
这个实现的关键是
-
在 WrapPanel 上设置 Orientation="Vertical" 以使内容垂直而不是水平缠绕,并且
在 ListBox 上设置 ScrollViewer.VerticalScrollBarVisibility="Disabled" 以便 ScrollViewer 知道将其高度限制为可用空间。
【讨论】:
我错过了 ScrollViewer.VerticalScrollBarVisibility="Disabled"。谢谢!!!!!!!!!!!!!!!!!! 3 年后...这篇文章还是很有帮助的,谢谢! 有用 8 年后,如果你只想垂直滚动换行面板:ScrollViewer.HorizontalScrollBarVisibility="Disabled">【参考方案2】:我相信要做到这一点,您需要编写自定义代码 - 您在覆盖 ItemsPanelTemplate 方面有正确的想法,但 WrapPanel 不会按照您想要的方式订购东西 - 它会按以下方式订购东西:
A B C D
E F G H
I J K L
而你可能想要它:
A D G J
B E H K
C F I L
另外,通过将它放在 ScrollViewer 中,就像告诉它它有一个无限大小的屏幕,所以结果只会是一行(因为 ScrollViewer 会给它所需的空间)。编写面板并不难,它基本上只有两个功能(测量和排列)。
【讨论】:
以上是关于使用 WrapPanel 和 ScrollViewer 在 WPF 中提供多列列表框的主要内容,如果未能解决你的问题,请参考以下文章
带有ScrollHeader和WrapPanel的ListView(ItemsPanel.ItemsPanelTemplate)
使用 WrapPanel 和 ScrollViewer 在 WPF 中提供多列列表框
将 WrapPanel 用作 ItemsPanel 的 ItemsControl - 结合“静态”子项和 ItemsSource