【问题标题】:Why StackPanel does not stretch its children vertically?为什么 StackPanel 不垂直拉伸其子项?
【发布时间】:2014-01-30 23:01:45
【问题描述】:

(WPF 新手)我正在查看 WPF 示例:

<Window x:Class="Attempt_XAML.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel>
        <Label HorizontalAlignment="Center">A Button Stack</Label>
        <Button HorizontalAlignment="Left">Button 1</Button>
        <Button HorizontalAlignment="Right">Button 2</Button>
        <Button Background="#FFA29494">Button 3</Button>
        <Button>Button 4</Button>
    </StackPanel>
</Window>

MS 中的注释说明:

Horizo​​ntalAlignment 和 StackPanel 中包含的内容的 VerticalAlignment。

但是,结果看起来与我的预期不同。 ButtonLabel 没有垂直拉伸,而只是水平拉伸(即它们不会在两个方向上填满 Window 的整个空间)为什么?

【问题讨论】:

  • 查看StackPanelOrientation 属性。此外,请记住,此面板只会使用其内容所需的空间。

标签: c# .net wpf


【解决方案1】:

Button 和 Label 没有垂直伸展,而只是水平伸展(即它们不会在两个方向上填充 Window 的整个空间)为什么?

要理解其中的原因,你至少需要对Panels有一个基本的了解。任何 Panel(例如 StackPanel)都使用测量-排列循环来决定其子元素的布局:

  • 在“测量”循环中,它为每个孩子分配一个尺寸
  • 在“排列”循环中,它将每个子项定位在其视图中

StackPanel 的主要特点是它有无限的空间——如果它的方向是Horizontal,它的水平空间是无限的,如果是Vertical,它的垂直空间是无限的。换句话说,它实际上并不关注它可用的大小(在它的方向上),而是声称拥有无限的空间。因此,回到您的示例,即使孩子的VerticalAlignment 可能是Stretch,它们实际上也不能被拉伸到无限大。

如果您需要一个扩展其子面板以填充可用空间的面板,那么Grid 就是一个很好的例子(默认情况下,Grid 将为每个孩子分配相等的总高度 - 或者您可以使用star sizing 调整比例)。如果您需要专门的布局行为,您也可以考虑创建自己的自定义面板。


编辑

澄清“无限空间”:我的意思是StackPanel 告诉它的孩子有无限的空间可用。如果你是 Button、Label 等,并且有无限的可用空间,你会怎么做?即使您的 VerticalAlignment 是“拉伸”,您也可能只占用您需要的最小空间,对吧?这就是发生的事情。与 Grid 对比,它告诉子控件它们有 x(有限)空间量——在这种情况下,按钮、标签等将填满 所有该空间(如果它们的 VerticalAlignment是“拉伸”)。

为说明上述情况,以这个自定义控件为例:

public class TestControl : ContentControl
{
    public string Description { get; set; }

    protected override Size MeasureOverride(Size availableSize)
    {
        System.Diagnostics.Debug.WriteLine("Size available for '" + Description + "': " + availableSize.Height);
        return base.MeasureOverride(availableSize);
    }
}

这实际上并没有做任何事情,只是报告已经分配了多少空间。现在,将测试控件放在GridStackPanel 中,然后进行比较:

<Grid Height="50">
    <Grid.RowDefinition />
    <Grid.RowDefinition />

    <local:TestControl Description="in Grid" />

    <StackPanel Grid.Row="1" Height="10">
        <local:TestControl Description="in StackPanel" />
    </StackPanel>
</Grid>

您将看到Grid 为其CustomPanel(上面的第一个)分配了25 的高度(其高度的一半)。不过,StackPanel 为其 CustomPanel 分配了 Infinity 的高度。

【讨论】:

  • 当您说infinite horizontal space 时,您的意思是它已将MaxWidthMaxHeight 设置为Infinity? W/H 设置为自动。
  • @newprint 不,这是不同的。高度/宽度属性可以影响面板分配给其子级的空间量——但在 StackPanel 的情况下,它总是分配其子级无限 空间。请参阅上面的编辑。
  • 感谢详细的回答。太糟糕了,这些信息都没有出现在官方文档中。全部信息。关于Orientation属性只是一句话。
【解决方案2】:

虽然StackPanel 中包含的ContentHorizontalAlignmentVerticalAlignment 的默认值都是拉伸的。但拉伸的方向由Orientation 属性控制。

如果将Orientation 设置为Vertical,则堆栈中没有定义宽度值的所有项目都只会被拉伸。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 2015-09-27
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多