如何强制网格(Grid)在必要时缩小包含滚动视图(ScrollViewer)的自动大小行?

10
如何创建这种布局?想法是让蓝色文本始终位于绿色元素正下方,但当空间不足时,绿色元素应放置在可滚动容器内(垂直滚动条可见)。
我尝试过StackPanel和Grid,但都失败了。如果将顶部RowDefinition的高度设置为“auto”(其中的ScrollViewer不显示其滚动条),则StackPanel根本不会收缩行。如果将其设置为星号,则蓝色文本会向下移动至至少一半的空间(取决于底部行的高度设置)。底行的高度可以是“自动”或带有VerticalAlignment设置为Top的星号,“蓝色文本”的行高必须至少与文本相同。当然,整个区域(黑色框)不能因其内容而被拉伸 - 它由窗口的大小确定。
如何实现?如有可能,请基于XAML进行回答。
2个回答

12

受到Eirik的方法启发,将贪婪容器放在其他紧密容器中限制它,我发现了一种非常简单的方法来实现我想要的效果。我只需要一个容器,先缩小其中一个子元素,然后(当第一个完全消失)再缩小第二个子元素。而且有这样的容器:DockPanel。如下所示:

<DockPanel LastChildFill="False">
    <DockPanel DockPanel.Dock="Top">
        <TextBlock DockPanel.Dock="Bottom" TextWrapping="Wrap" Grid.Row="1">Automatically wrapped text of unknown length.</TextBlock>
        <ScrollViewer>
            <TextBlock TextWrapping="Wrap">In this case the element is too big to fit inside whole space (the black box) with the blue text below. I want the scrollbar to be shown instead of moving the blue text outside of the black box (and clipped)</TextBlock>
        </ScrollViewer>
    </DockPanel>
</DockPanel>

就是这么简单! :) 我希望能帮到某些人。


1
这确实帮了我很多。我也在尝试做同样的事情,这个方法非常有效。感谢您分享最终的解决方案! - Richard Irons

3
<Grid Name="outerGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <Canvas>
        <Grid MaxWidth="{Binding ElementName=outerGrid, Path=ActualWidth}" MaxHeight="{Binding ElementName=outerGrid, Path=ActualHeight}">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <ScrollViewer Width="{Binding ElementName=outerGrid, Path=ActualWidth}">
                <TextBlock TextWrapping="Wrap">In this case the element is too big to fit inside whole space (the black box) with the blue text below. I want the scrollbar to be shown instead of moving the blue text outside of the black box (and clipped)</TextBlock>
            </ScrollViewer>
            <TextBlock TextWrapping="Wrap" Grid.Row="1">Automatically wrapped text of unknown length.</TextBlock>
        </Grid>
    </Canvas>
</Grid>

自动高度将增长以匹配该行内容的高度。
星形高度将使该行增长到填充网格的其余高度,防止ScrollViewer增长超出可见部分。
编辑:如果您将Grid放在另一个Grid中,就像上面的XAML一样,您应该会得到所需的行为。外部行的第二行充当“填充器”,以填充外部Grid的其余空间。
编辑2:尝试上面编辑过的XAML。我将内部Grid放在Canvas中(以防止裁剪),并将内部Grid的MaxWidth和MaxHeight绑定到外部Grid的ActualWidth和ActualHeight,以使内部Grid与外部Grid保持相同大小。
编辑3:添加了对ScrollViewer宽度的绑定,以使其与其余部分保持相同的宽度。

这很好,但我希望底部(蓝色)文本放置在上方元素的正下方(尽可能高)。在您的示例中,它放置在窗口(网格)的底部。我希望文本下面有空白空间。 - P.W.
1
这个方法看起来不错,但你测试过吗?不幸的是它不起作用。当你缩小整个窗口(因此没有足够的空间)时,控件会被裁剪。内部表格没有被缩小。我猜测当行设置为“自动”(在这种情况下是外部表格),即使它比整个表格大,它也永远不会被缩小。所以你看,这并不简单。PS:我认为我会立即得到正确的答案,因为在WPF中可以做任何事情...而且这里有很多专家,但看起来WPF并不像它所说的那么灵活。 - P.W.
在这种情况下,它几乎可以工作,但是当水平拉伸窗口以匹配内容文本的实际宽度时,ScrollViewer的宽度会跳动。这意味着滚动条不会随着窗口边框向右移动,直到下一个单词可以适合一行。我尝试将HorizontalAlignment设置为Stretch,但没有帮助。 - P.W.
请参考编辑3,修复跳动的ScrollViewer宽度。 - Eirik
这一个最终按预期工作了! :) 然而在此期间我发现了更简单的解决方案。我会很快把它作为回答附上。没有你我做不到,所以我给你加上一个赞 :) 谢谢! - P.W.

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