StackPanel 内的 ScrollViewer 的宽度会自动随内容的宽度变化

Width of ScrollViewer inside StackPanel automatically change with it's Content's width

一个ScrollViewerWidth如果这样使用的话,仍然是"normal":

<Grid>
    <ScrollViewer>
        <Rectangle Width="2500"/>
    </ScrollViewer>
</Grid>

说 "Normal" 我的意思是 ScrollViewerWidth 将与 Grid 相同(在我的例子中是 1500)我自己没有提到他们的 Width。至少我是这么知道的。

但是,如果以上部分像这样放在 StackPanel 中:

<StackPanel Orientation="Horizontal">
    <Grid>
        <ScrollViewer>
            <Rectangle Width="2500"/>
        </ScrollViewer>
    </Grid>
</StackPanel>

然后 ScrollViewerWidth 变为 2500,因为它是内容的 Width

这是什么原因?

XAML中的布局过程有两个阶段测量排列

测量阶段,通常,大多数小组会询问他们的child任"What size do you want to be?"(这将有效地走下树)。而 children 的 parent 可以根据它的 children 来决定它想要的大小。它 returns 这个 Size 在它的 MeasureOverride 方法中。

一切都测量完后,就可以在屏幕上实际排列和布局了。这是确定元素的实际 大小的时候。系统首先告诉每个元素 "This is how much space you have." 然后每个面板,从顶部开始,然后可以告诉它 child 在其 space 中的位置以及它实际有多少 space必须占用(通过在 parent 自定义面板的 ArrangeOverride 方法中对每个 child 调用 Arrange 来完成)。

您可以查看此 here 的完整文档。

因此在您的两个示例中,由于 Grids 和 StackPanel 的行为方式不同,结果不同:

  1. 以网格为根,在您的顶部示例中,它占用可用的 space 并告诉它的 children 他们 必须 装进去。所以 ScrollViewer 说它想要更大,因为它是 child 矩形,但最后 Grid 说你只有 1500 个 space 单位,因为这就是给定的全部。因此,如果您打开 HorizontalScrollBarVisibility 让您平移以查看整个矩形,ScrollViewer 将显示一个滚动条。

  2. 以 StackPanel 为根,它将扩展自身以容纳其 children 的大小。因此,当 ScrollViewer 告诉 Grid 它希望其内容达到这个大小时,它会通过 Grid 向上传递到 StackPanel。到了 Arrange 时,StackPanel 告诉 Grid 它拥有它请求的所有 space,这是 Rectangle 想要的额外 space。这个额外的 space 只是在最后显示时被 page/window 剪掉。

这就是为什么有如此多不同的布局面板可用的原因,因为它们在这两个步骤中的行为都不同,以排列一个或多个内容项以获得所需的效果。这也是为什么在任何地方都使用 StackPanels 会很棘手,因为与其他表现更好的面板相比,它们总是贪婪的 'predictably'.