使用WrapPanel和ScrollViewer在WPF中创建多列Listbox

5
我正在制作一个简单的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>
2个回答

31

看起来你的思路是正确的:用WrapPanel替换ListBox中的ItemsPanelTemplate,将WrapPanel的方向设置为垂直,并将ScrollViewer.VerticalScrollBar设置为禁用应该就足够了。

这对我有效:

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

这应该导致它在一个完整的列垂直地呈现,换行,然后继续在下一列中水平滚动(但不是垂直滚动),如图所示:

ListBox with WrapPanel wrapping vertically

此实现中的关键点是:

  1. 在WrapPanel上设置Orientation =“Vertical”,使其垂直而非水平换行,以及
  2. 在ListBox上设置ScrollViewer.VerticalScrollBarVisibility =“Disabled”,以便ScrollViewer知道限制其高度为可用空间。

我忘了加上 ScrollViewer.VerticalScrollBarVisibility="Disabled"。谢谢!!!!!!!! - Gerardo Grignoli
三年后...这篇文章仍然非常有用,谢谢! - GETah
有用的8年后,如果您想要垂直滚动Wrap Panel:ScrollViewer.HorizontalScrollBarVisibility="Disabled"> - user3704628

0

我认为要做到这一点,您需要编写自定义代码 - 您在覆盖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会提供所需的空间)。编写面板并不难,基本上只需要两个函数(Measure和Arrange)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接