使用 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.Horizo​​ntalScrollbar=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.Horizo​​ntalScrollBarVisibility="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 中提供多列列表框的主要内容,如果未能解决你的问题,请参考以下文章

UWP 中 ListBox 内的 WrapPanel

带有ScrollHeader和WrapPanel的ListView(ItemsPanel.ItemsPanelTemplate)

使用 WrapPanel 和 ScrollViewer 在 WPF 中提供多列列表框

将 WrapPanel 用作 ItemsPanel 的 ItemsControl - 结合“静态”子项和 ItemsSource

WPF wrappanel:管理水平和垂直行为

WPF学习第七章 WrapPanel和DockPanel面板