wpf - 如何设置垂直 WPF WrapPanel 以使用尽可能多的列
问题描述
我有一个带有 WrapPanel 作为 ItemsPanel 的 ItemsControl。ItemsControl 位于 ScrollViewer 中。
根据窗口的宽度,ItemsControl/WrapPanel 应该有更多的列来更多地使用屏幕(并且用户必须减少滚动)。
如果我将 WrapPanel 设置为 Orientation="Horizontal" 它会按预期工作。但是,如果我将方向设置为“垂直”,则 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" 时仅显示一列。
解决方案
好的,我想出了一个解决方案,那就是纯 XAML。
所以基本上我有一个网格。有两排。网格内部是两个几乎相同的 ItemsControl,带有绑定和 WrapPanel。第一个有一个带有 Orientation="Horizontal" 的 WrapPanel。它仅用于计算第二个 ItemsControl 的边界。因此它的可见性=“隐藏”。它也只跨越第一行。
第二个 ItemsControl 具有 Orientation="Vertical" 的 WrapPanel。它的高度绑定到第一个 ItemsControl 的 ActualHeight。因此它被迫使用多个列,因为高度不能高于 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 变得更小。之后第二个立即变小。但这似乎是一个额外的步骤。
推荐阅读
- arrays - Ajax 响应在数据表中显示为单个字母
- php - Having issue with .htacces file and get method in php
- php - 删除数组foreach mysql中的重复项
- c# - Setting fixed major grid marks independent of data range
- regex - 为什么 Unicode 字符 'MINUS SIGN' (U+2212) 不在正则表达式 unicode 组 \p{Pd} (Dash_Punctuation) 中?
- mysql - How to get all children of the children of the specific parent
- javascript - What is the point of having multiple values after a return statement?
- d3.js - Positioning the text straight in horizontal stacked bar in d3
- java - Spring Data Jpa - How to perform roll back?
- python - 散景图未拉伸以填充剩余空间