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 为 Horizontal 时。它不会出现在水平 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 和 * 行为异常?的主要内容,如果未能解决你的问题,请参考以下文章