StackPanel 中的网格:为啥 auto 和 * 行为异常?

Posted

技术标签:

【中文标题】StackPanel 中的网格:为啥 auto 和 * 行为异常?【英文标题】:Grid inside a StackPanel: why do auto and * behave strangely?StackPanel 中的网格:为什么 auto 和 * 行为异常? 【发布时间】:2012-01-01 14:10:33 【问题描述】:

我的 google 和 *** search-fu 都让我失望了,所以我向社区提出了这个问题。

(这都是使用 VS2010 和 .NET 4.0 生成的,在空白的默认 WPF 解决方案中)

考虑以下 XAML:

<StackPanel Orientation="Horizontal">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Border Name="aborder" Grid.Column="0" Grid.ColumnSpan="2" 
                    Background="Red" Width="200"/>
        <Border Name="aborder2" Background="Green"/>

    </Grid>
</StackPanel>

你预测“aborder2”的宽度是多少?

如果您猜“20 像素”,那您就错了。正确答案是 110 像素。

考虑一下这个 XAML:

    <StackPanel Orientation="Horizontal">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Border Name="aborder" Grid.Column="0" Grid.ColumnSpan="2" 
                    Background="Red" Width="200"/>
        <Border Name="aborder2" Background="Green"/>

    </Grid>
</StackPanel>

你预测“aborder2”的宽度是多少?

如果您猜的是 20 像素或 110 像素,那您就错了。正确答案是 200 像素。

我无法弄清楚这一点,这让我发疯。似乎答案应该是显而易见的;显然,自动填充网格列和堆栈面板之间存在一些交互,导致网格崩溃。但这似乎没有任何意义 - 管理这种行为的任何规则似乎都是任意的。为什么是 110 像素?为什么不是 109 像素或 100 像素?如果自动调整大小的列无法完全扩展或其他原因,我会理解,但是让固定宽度的列随机忽略它的宽度,这让我的开发人员被烧毁了。

任何帮助或指路明灯将不胜感激!

【问题讨论】:

为什么 aborder2 没有得到 Grid.Column? 我没想过要放一个,因为它应该默认为第 0 列。我只是测试了它,明确设置该列似乎没有什么区别。 有答案但我得先回家 值得注意的是,这只发生在 StackPanel Orientation 为 Horizo​​ntal 时。它不会出现在水平 WrapPanel 中,即使它具有类似的布局测量规则。我猜这是一个错误。我通常建议避免将想要扩展(在堆栈方向)的东西放入 StackPanel,因为满足约束的最小尺寸很少是理想的行为。 【参考方案1】:

我不知道为什么第一个示例没有正确渲染

第二个是因为Auto 的意思是“与内容大小相同”,但是您在 Column2 中没有任何内容,因此 Column2 在 0px 处呈现。您在 Column1 中有跨越 2 个单元格的东西,但由于 Column2 以 0 像素呈现,这意味着 Column1 被拉伸到 200 像素。默认情况下,Grid 会扩展它们的子元素以填充 Cell 中的所有可用空间,因此这会使 aborder2 拉伸到 200 像素而不是 20 像素。

我认为第一个示例可能是类似的情况,其中 Column2 渲染为 0px,因为它没有内容,但是我不确定它为什么将 aborder2 设置为 110 的宽度。 110 似乎来自(GridWidth / TotalColumns) + (1stColumnWidth / TotalColumns * NumberOfStarColumns),所以我认为这是一个错误。

附带说明,您可以设置 Column1 的 MaxWidth="20" 以强制 Column1 始终呈现为 20px

【讨论】:

好吧,至少您导出了确定 110px 的公式,因此您赢得了投票!我自己找不到任何关系。 第二列在第一个示例中呈现为 90 像素,而不是 0。第一列以 110 呈现(110 + 90 = 200 以容纳 aborder1,虽然我不知道为什么它们以这些尺寸呈现),aborder2 正在拉伸以填充它。 有趣的观察发现设置 MaxWidth 会阻止调整大小。 我想我会将此标记为答案,因为编辑提供了一种解决方法,而且似乎没有更多即将到来。【参考方案2】:

没有答案,但它似乎也发生在 Silverlight 中。我假设在排列和测量过程中存在一些错误。如果您在其中放置自定义控件而不是边框​​并覆盖度量和排列方法,您可能会更好地了解正在发生的事情。

为了解开 110 的来源之谜,我猜是 (200 - 20) / 2 + 20

编辑:我尝试了其他一些公式,但没有成功,看起来更像:

(200 + 20) / 2

【讨论】:

以上是关于StackPanel 中的网格:为啥 auto 和 * 行为异常?的主要内容,如果未能解决你的问题,请参考以下文章

网格和stackpanel之间的WPF组合

StackPanel 孩子自动调整大小

为啥这个数据网格以奇怪的顺序排序?

StackPanel中的WebBrowser不会在WPF中扩展到其内容大小

WPFWPF为stackpanel设置滚动条

如何将 ListView 停靠在 StackPanel 上?