布局面板内的内容不滚动

Content inside layout panel not scrolling

假设我有一个简单的 Windows 10 UWP 应用程序

<Page
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    <!-- etc -->
    >

    <Grid>

        <ListView>
            <TextBlock Text="Sample text"/>
            <TextBlock Text="Sample text"/>
            <TextBlock Text="Sample text"/>
            <!-- & many more -->
        </ListView>

    </Grid>

</Page>

大量的 ListView 项目导致它溢出和滚动,正如预期的那样:

但是,如果我需要添加另一个控件作为 ListView 的同级控件,就像这样(为简单起见,将 Grid 替换为 StackPanel)

<Page...>

    <StackPanel>

        <ListView>
            <TextBlock Text="Sample text"/>
            <TextBlock Text="Sample text"/>
            <TextBlock Text="Sample text"/>
            ...
        </ListView>

        <StackPanel>
            <TextBlock Text="StackPanel at the bottom"/>
            <Button Content="Click me"/>
        </StackPanel>

    </StackPanel>

</Page>

然后滚动条消失,ListView 不再可滚动。内容刚刚被剪裁/切断超过 window 的底部。

这是怎么回事,我怎样才能让它再次滚动?

关键是ScrollViewer control。 ListViews 和 GridViews 之所以可以滚动,首先是因为它们内置了 ScrollViewer。

当您将 ListView 放置在父布局面板(例如 StackPanel 或 Grid 行)中时,如果 ListView 的高度大于视口,则父面板将成为 ListView 的完整高度。但是 StackPanel 没有实现 ScrollViewer 所以它不能滚动,你最终得到一个 StackPanel 延伸出视口的底部边缘。

解决方法很简单:将有问题的父布局面板放在 ScrollViewer 中

<Page...>

    <ScrollViewer VerticalScrollBarVisibility="Auto"> <!--default is "Visible"-->
        <StackPanel>

            <ListView>
                <TextBlock Text="Sample text"/>
                <TextBlock Text="Sample text"/>
                <TextBlock Text="Sample text"/>
                ...
            </ListView>

            <StackPanel>
                <TextBlock Text="StackPanel at the bottom"/>
                <Button Content="Click me"/>
            </StackPanel>

        </StackPanel>
    </ScrollViewer>

</Page>

ScrollViewer API reference - MSDN

要为 binaryfunt 的回答添加更多上下文:这取决于您使用的面板的布局逻辑!

事先注意:ListView 内部默认有自己的 ScrollViewer

在布置 children 时,Grid 通常会告诉其 children 它们应该适合网格的边界。在 ListView 的情况下,它很乐意这样做,并且它自己的内部 ScrollViewer 处理它的 children 滚动。

另一方面,

StackPanel 告诉它的 children 他们实际上有无限的 space 可以在它的堆叠方向上布局 - 所以你的 ListView 不知道它有将自己限制在 StackPanel 的高度,因为 StackPanel 没有告诉它这样做,所以 ListView 永远不需要使用它自己的 ScrollViewer 因为它认为它有无限 space.

现在,将 StackPanel 放在 ScrollViewer 中本身并没有帮助 - 如果你将 ScrollViewer 放在 StackPanel 中,你会遇到同样的问题ListView 确实如此——它认为它有无限的 space,因此永远不需要滚动它的内容。但是,将 ScrollViewer 放在 Grid 中,网格将为 ScrollViewer 提供定义的布局尺寸,因此如果 ScrollViewer 中的任何内容太大,现在都会滚动。

在这个StackPanel里面放一个ListView在这个ScrollViewer里面? ListView 仍然认为它有无限的 space 因此永远不需要使用自己的滚动条,但它也禁用和虚拟化以及 ListView 通常会有的性能增强,因为他们依赖它interal ScrollViewer 居然被放太用了。

(binaryfunt 的 XAML 答案有效。)