如何设置垂直WPF WrapPanel以使用尽可能多的列

btqmn9zl  于 2023-11-20  发布在  其他
关注(0)|答案(3)|浏览(143)

我有一个WrapPanel作为ItemsPanel的ItemsControl。ItemsControl在ScrollViewer中。
根据窗口的宽度,ItemsControl/WrapPanel应该有更多的列,以更多地利用屏幕(并且用户必须减少滚动)。
如果我将WrapPanel设置为Orientation=“Horizontal”,它会像预期的那样工作。但是如果我将Orientation设置为“Vertical”,ItemsControl/WrapPanel只显示一列。
不同的是,我喜欢像报纸专栏一样的专栏,比如:

A   E   I
B   F   J
C   G
D   H

字符串
但如果WrapPanel设置为Horizontal,则列如下所示:

A   B   C
D   E   F
G   H   I
J


我如何设置WrapPanel以实现这种行为?
我当然可以限制高度.当然,我可以实现这一点与一些聪明的逻辑,考虑到项目的数量从源以及窗口的宽度.但这将是复杂的,可能是一个混乱,没有人会理解(甚至我自己,如果我回顾这在几年).
我希望这样的东西已经存在于WPF中。
下面是伪XAML代码

<ScrollViewer>
    <StackPanel>

        <!-- Some other stuff -->

        <ItemsControl ItemsSource="{Binding … }">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Width="300"><!-- … --></Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <!-- Some more other stuff -->

    </StackPanel>
</ScrollViewer>


它与Orientation=“Horizontal”(但单元格顺序错误)一起工作,但当Orientation=“Vertical”时只显示一列。

6qftjkof

6qftjkof1#

我相信Orientation="Vertical"是你正在寻找的选项。它将尝试在 Package 到新列之前填充一列。

A __D __G
| | | | | 
B | E | .
| | | | .
C_| F_| .->

字符串
您遇到的麻烦是StackPanel允许WrapPanel拥有无限的垂直布局空间,因此不必换行。
若要解决此问题,请将StackPanel更改为WrapPanel或其他不允许无限布局空间的控件。

示例

<WrapPanel>
    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <Rectangle Height="50" Width="50" Fill="#F000"/>
        <Rectangle Height="50" Width="50" Fill="#F111"/>
        <Rectangle Height="50" Width="50" Fill="#F222"/>
        <!- ...  ->
        <Rectangle Height="50" Width="50" Fill="#F111"/>
        <Rectangle Height="50" Width="50" Fill="#F000"/>
    </ItemsControl>    
</WrapPanel>

结果


的数据

igsr9ssn

igsr9ssn2#

好吧,我想出了一个解决方案,那就是纯XAML。
所以基本上我有一个网格。有两行。在网格内是两个几乎相同的ItemsControl与绑定和WrapPanel。第一个有一个WrapPanel与Orientation=“Horizontal”。它只是在那里计算第二个ItemsControl的边界。因此,它的可见性=“Hidden”。它也只跨越第一行。
第二个ItemsControl的WrapPanel的Orientation=“Vertical”。它的Height绑定到第一个ItemsControl的ActualHeight。因此,它被迫使用多个Columns,因为高度不能高于ItemsControl #1的高度。第二个ItemsControl跨越两行(这很重要,否则高度可能会卡住,当窗口 * 关闭时)。
这不是一个很好的解决方案。更像是蛮力。但它当然有效。第一个ItemsControl计算外部大小。我将此大小强制到第二个,这比可以以一个很好的模式分布项目。

<ScrollViewer>
    <StackPanel>

        <!-- Some other stuff -->

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <!-- first ItemsControl, to calculate the outer boundaries with --> 
            <ItemsControl ItemsSource="{Binding … }" 
                          Name="Calculating_Size"
                          Visibility="Hidden">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid Width="300"><!-- … --></Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

            <!-- Second ItemsControl with fixed size for Vertical WrapPanel --> 
            <ItemsControl ItemsSource="{Binding … }" 
                          Height="{Binding ActualHeight, ElementName=Calculating_Size}"
                          Grid.RowSpan="2">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Vertical" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid Width="300"><!-- … --></Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

        <!-- Some more other stuff -->

    </StackPanel>
</ScrollViewer>

字符串

*第二行的原因是,如果第一个WrapPanel重新组织,因为宽度增加,它仍然与高度固定,因为行不能变小,第二个ItemsControl。但是,如果第二个ItemsControl跨越两行,第一行可以独立于第二个ItemsControl变小。第二个在之后立即变小。但这似乎是一个额外的步骤。

5kgi1eie

5kgi1eie3#

对我来说,答案是通过将WrapPanel绑定到父ScrollContentPresenter来约束它的高度

<ListBox>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Vertical"
                       Height="{Binding (FrameworkElement.ActualHeight), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}">
                </WrapPanel>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

字符串

相关问题