如何让StackPanel的孩子向下填充最大空间?

时间:2009-02-20 10:47:24

标签: wpf xaml autolayout autoresize dockpanel

我只想在左侧显示流动文本,在右侧显示帮助框。

帮助框应该一直延伸到底部。

如果您取出下方的外部StackPanel,它可以很好地工作。

但是由于布局的原因(我正在动态插入UserControl),我需要包装StackPanel。

如何让GroupBox扩展到StackPanel的底部,你可以看到我已经尝试过:

  • VerticalAlignment =“Stretch”
  • VerticalContentAlignment =“Stretch”
  • 高度= “自动”

XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600">
    <StackPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                Background="Beige" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" />
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </StackPanel>
</Window>

答案:

感谢Mark,使用DockPanel而不是StackPanel将其清除。一般来说,我发现自己现在越来越多地使用DockPanel进行WPF布局,这是固定的XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600" MinWidth="500" MinHeight="200">
    <DockPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            MinWidth="400"
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <Border CornerRadius="3" Background="Beige">
                    <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" 

                Padding="5"/>
                </Border>
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </DockPanel>
</Window>

5 个答案:

答案 0 :(得分:310)

听起来你想要一个StackPanel,其中最后一个元素占用了所有剩余的空间。但为什么不使用DockPanel?使用DockPanel装饰DockPanel.Dock="Top"中的其他元素,然后您的帮助控件可以填充剩余空间。

XAML:

<DockPanel Width="200" Height="200" Background="PowderBlue">
    <TextBlock DockPanel.Dock="Top">Something</TextBlock>
    <TextBlock DockPanel.Dock="Top">Something else</TextBlock>
    <DockPanel
        HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" 
        Height="Auto" 
        Margin="10">

      <GroupBox 
        DockPanel.Dock="Right" 
        Header="Help" 
        Width="100" 
        Background="Beige" 
        VerticalAlignment="Stretch" 
        VerticalContentAlignment="Stretch" 
        Height="Auto">
        <TextBlock Text="This is the help that is available on the news screen." 
                   TextWrapping="Wrap" />
     </GroupBox>

      <StackPanel DockPanel.Dock="Left" Margin="10" 
           Width="Auto" HorizontalAlignment="Stretch">
          <TextBlock Text="Here is the news that should wrap around." 
                     TextWrapping="Wrap"/>
      </StackPanel>
    </DockPanel>
</DockPanel>

如果您所在的平台没有DockPanel(例如WindowsStore),则可以使用网格创建相同的效果。以下是使用网格完成的上述示例:

<Grid Width="200" Height="200" Background="PowderBlue">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0">
        <TextBlock>Something</TextBlock>
        <TextBlock>Something else</TextBlock>
    </StackPanel>
    <Grid Height="Auto" Grid.Row="1" Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <GroupBox
            Width="100"
            Height="Auto"
            Grid.Column="1"
            Background="Beige"
            Header="Help">
            <TextBlock Text="This is the help that is available on the news screen." 
              TextWrapping="Wrap"/>
        </GroupBox>
        <StackPanel Width="Auto" Margin="10" DockPanel.Dock="Left">
            <TextBlock Text="Here is the news that should wrap around." 
              TextWrapping="Wrap"/>
        </StackPanel>
    </Grid>
</Grid>

答案 1 :(得分:100)

发生这种情况的原因是因为堆栈面板测量具有正无穷大的每个子元素作为其堆叠元素的轴的约束。子控件必须返回它们想要的大小(正无穷大不是任一轴上MeasureOverride的有效返回),因此它们返回所有内容都适合的最小尺寸。他们无法知道他们真正需要填充多少空间。

如果您的视图不需要滚动功能且上面的答案不符合您的需求,我建议您实施自己的面板。您可以直接从StackPanel派生,然后您需要做的就是更改ArrangeOverride方法,以便在子元素之间划分剩余空间(为每个元素提供相同数量的额外空间)。如果元素给予的空间超出了他们想要的空间,那么元素应该会很好。但是如果你给它们的数量减少,你就会开始看到毛刺。

如果你想能够滚动整个东西,那么恐怕事情会变得更加困难,因为ScrollViewer为你提供了无限的工作空间,这将使你处于与最初是儿童元素。在这种情况下,您可能希望在新面板上创建一个新属性,以便指定视口大小,您应该能够将其绑定到ScrollViewer的大小。理想情况下,您将实现IScrollInfo,但如果您要正确实现所有这些,那将开始变得复杂。

答案 2 :(得分:55)

另一种方法是使用具有一列和 n 行的Grid。将所有行高设置为Auto,将最下面的行高设置为1*

我更喜欢这种方法,因为我发现Grids比DockPanels,StackPanels和WrapPanels具有更好的布局性能。但除非你在ItemTemplate中使用它们(对大量项目执行布局),否则你可能永远不会注意到。

答案 3 :(得分:14)

您可以使用StackPanel的modified version

<st:StackPanel Orientation="Horizontal" MarginBetweenChildren="10" Margin="10">
   <Button Content="Info" HorizontalAlignment="Left" st:StackPanel.Fill="Fill"/>
   <Button Content="Cancel"/>
   <Button Content="Save"/>
</st:StackPanel>

第一个按钮将被填充。

您可以通过Nuget安装它:

Install-Package SpicyTaco.AutoGrid

我还建议您查看wpf-autogrid。它对WPF中的表单非常有用,而不是DockPanel,StackPanel和Grid,并且非常容易和优雅地解决了拉伸问题。只需看看github上的自述文件。

<st:AutoGrid Columns="160,*" ChildMargin="3">
    <Label Content="Name:"/>
    <TextBox/>

    <Label Content="E-Mail:"/>
    <TextBox/>

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>

答案 4 :(得分:-1)

你可以做的事情很多:

1:将Orientation设置为垂直

<StackPanel Orientation="Vertical"></StackPanel>
  1. Height的{​​{1}}设置为与窗口相同:

  2. 当然,您可以将属性

    组合在一起
    StackPanel

    安装NuGets等等,你不需要做大量的额外工作。

    修改

    您也可以将StackPanel放在ScrollViewer中。这将允许您控制GroupBox的高度而不会牺牲内容可见性。

    <StackPanel Orientation="Vertical" Height="600"></StackPanel>