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

时间:2009-05-25 21:24:29

标签: wpf data-binding xaml listbox

我正在创建一个简单的LOB应用程序,该应用程序从XML文件加载数据并将其显示在列表中,并带有几个按钮进行编辑。

在我的第一次尝试中,一切都很好,只是列表在一个长列中向下滚动。我希望数据包装,以便在窗口的底部开始第二列,依此类推 - 如果你调整Window的大小,数据应该相应地调整大小。

首先,我将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>

2 个答案:

答案 0 :(得分:30)

看起来你是在正确的轨道上:用一个WrapPanel替换ListBox中的ItemsPanelTemplate,将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>

这应该导致它垂直渲染一个完整的列,换行,然后继续下一列,根据需要水平滚动(但不是垂直),如图所示:

ListBox with WrapPanel wrapping vertically

此实现中的关键事项是

  1. 在WrapPanel上设置Orientation =“Vertical”,以便事物垂直而不是水平地包裹,并且
  2. 在ListBox上设置ScrollViewer.VerticalScrollBarVisibility =“Disabled”,以便ScrollViewer知道将其高度限制在可用空间。

答案 1 :(得分: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会给它提供尽可能多的空间)。编写一个面板并不难,它基本上只是两个功能(测量和排列)。