WPF中的WrapPanel在ViewBox中的最大尺寸

3
在我的程序中,我有一个放在viewbox里的WrapPanel。这个WrapPanel实际上是ItemsControl的ItemsPanelTemplate,包含一些绑定的项,它们的大小都可能不同。
<Viewbox Name="ViewWindow" Margin="10">
  <Grid>
    <ItemsControl ItemsSource="{Binding Path=Items}">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <WrapPanel Orientation="Vertical" MaxHeight="600"/>
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>

所有这些的目标是让所有项的大小适合单个屏幕。Viewbox通过缩放内容以适应所有内容来处理此问题。WrapPanel中的每个项都是用户定义的文本,因此它们的大小可能各不相同。我尝试使用WrapPanel完成的任务是屏幕上的结果文本尽可能大。我一直通过设置WrapPanel MaxHeight来实现这一点,以便如果它们太高,就将项目包装到更多列中,但这是一种笨拙的方法,并且我发现对于不同的项目组,MaxHeight需要不同的值。
例如,假设ItemsControl绑定的项只显示字母表中的每个字母。如果没有任何方法强制项目换行到多个列,则会得到一个非常高的列,其中文本非常小,但如果我们设置WrapPanel的MaxHeight,则可以将项目强制换行到多个列中,文字在屏幕上会变得更大。
A    F    K    P    U    Z
B    G    L    Q    V
C    H    M    R    W
D    I    N    S    X
E    J    O    T    Y

我这样做是错的吗?有比WrapPanel更好的控件吗?我需要创建某种自定义面板才能得到我想要的结果吗?
感谢您提供的任何帮助。
编辑:
如果使用UniformGrid不起作用,举个例子,假设我有这5个项目(每个字母代表一个不同的项目):
A    C    E
A    C    E
A    D    E
B    D    E

如果使用UniformGrid,所有的项目尺寸都将采用元素E的大小,并且它们会在屏幕上占据更多的空间。


你觉得使用UniformGrid作为ItemsPanel怎么样?我认为这会在添加项目时添加行和列。 - Matt Burland
1
你无法以任何简单的方式完成这个任务。如果一个Wrap Panel位于Viewbox内部,它永远不需要换行,因为Viewbox会将其缩小以适应。 - Phil
1个回答

2
这是否实现了您所要做的事情:
        <ItemsControl ItemsSource="{Binding Path=Items}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid IsItemsHost="True"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>

使用您提供的字母表,我将其布局如下:

A B C D E F
G H I J K L
M N O P Q R
S T U V W X
Y Z

现在,如果对您来说重要的是按列而不是按行排列它们,那么就有点棘手。以下是一种非常hacky的方法,可以使它们按列排列:

<ItemsControl ItemsSource="{Binding Path=Items}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid IsItemsHost="True"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}">
                        <TextBlock.LayoutTransform>
                            <TransformGroup>
                                <ScaleTransform ScaleX="-1"/>
                                <RotateTransform Angle="-90"/>
                            </TransformGroup>
                        </TextBlock.LayoutTransform>
                    </TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="-1"/>
                    <RotateTransform Angle="-90"/>
                </TransformGroup>
            </ItemsControl.LayoutTransform>
        </ItemsControl>

我认为您不能告诉一个统一的网格以列为首来排列事物。


我不认为UniformGrid会满足我的需求,因为这些项的高度是不同的,而我不希望它们的布局方式使得它们都占用与最大项相同的空间。 - aalex675
@aalex675:所以你想尽可能地紧密地打包,完全没有任何秩序吗?即使是WrapPanel也会有列占据列中最大项的宽度。 - Matt Burland
1
我不关心列的宽度是否相等,这没有问题。我想我需要的是WrapPanel根据其中项的高度和宽度计算出最佳的MaxHeight。我开始想知道我是否可以在ValueConverter中完成这个操作,只需获取面板中所有项的高度和宽度即可计算出结果。 - aalex675

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