393

我只想要左边的流动文本,右边的帮助框。

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

如果你把StackPanel下面的外层拿出来,效果很好。

但是出于布局的原因(我正在动态插入 UserControls),我需要将StackPanel.

如您所见,我如何使GroupBox向下延伸到底部,我已经尝试过:StackPanel

  • VerticalAlignment="Stretch"
  • VerticalContentAlignment="Stretch"
  • Height="Auto"

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>

回答:

谢谢马克,使用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>
4

4 回答 4

375

听起来你想要一个StackPanel最终元素用完所有剩余空间的地方。但为什么不使用 a DockPanel?用装饰其他元素DockPanelDockPanel.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>
于 2009-02-20T11:25:07.600 回答
114

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

如果您的视图不需要具有滚动功能并且上面的答案不适合您的需求,我建议您实现自己的面板。您可能可以直接从 StackPanel 派生,然后您需要做的就是更改ArrangeOverride方法,以便它在其子元素之间划分剩余空间(给它们每个相同数量的额外空间)。如果给元素的空间比他们想要的多,它们应该渲染得很好,但是如果你给它们的空间少,你就会开始看到故障。

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

于 2009-02-20T11:44:52.843 回答
70

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

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

于 2009-02-20T17:30:40.937 回答
23

您可以使用SpicyTaco.AutoGrid - 的修改版本StackPanel

<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

我建议看看SpicyTaco.AutoGrid。它对于 WPF 中的表单而不是 非常有用DockPanelStackPanel并且Grid可以非常轻松优雅地解决拉伸问题。只需查看 GitHub 上的自述文件。

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

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

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>
于 2016-03-10T21:16:15.100 回答