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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/569095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:04:12  来源:igfitidea点击:

How to get StackPanel's children to fill maximum space downward?

wpfxamlautolayoutautoresizedockpanel

提问by Edward Tanguay

I simply want flowing text on the left, and a help box on the right.

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

The help box should extend all the way to the bottom.

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

If you take out the outer StackPanelbelow it works great.

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

But for reasons of layout (I'm inserting UserControls dynamically) I need to have the wrapping StackPanel.

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

How do I get the GroupBoxto extend down to the bottom of the StackPanel, as you can see I've tried:

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

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

XAML:

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>

Answer:

回答:

Thanks Mark, using DockPanelinstead of StackPanelcleared it up. In general, I find myself using DockPanelmore and more now for WPF layouting, here's the fixed XAML:

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

采纳答案by Mark Heath

It sounds like you want a StackPanelwhere the final element uses up all the remaining space. But why not use a DockPanel? Decorate the other elements in the DockPanelwith DockPanel.Dock="Top", and then your help control can fill the remaining space.

听起来你想要一个StackPanel最终元素用完所有剩余空间的地方。但为什么不使用DockPanel?装修中的其他元素DockPanelDockPanel.Dock="Top",然后你的帮助控制可以填补剩余空间。

XAML:

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>

If you are on a platform without DockPanelavailable (e.g. WindowsStore), you can create the same effect with a grid. Here's the above example accomplished using grids instead:

如果您在一个没有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>

回答by Caleb Vear

The reason that this is happening is because the stack panel measures every child element with positive infinity as the constraint for the axis that it is stacking elements along. The child controls have to return how big they want to be (positive infinity is not a valid return from the MeasureOverridein either axis) so they return the smallest size where everything will fit. They have no way of knowing how much space they really have to fill.

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

If your view doesn't need to have a scrolling feature and the answer above doesn't suit your needs, I would suggest implement your own panel. You can probably derive straight from StackPanel and then all you will need to do is change the ArrangeOverridemethod so that it divides the remaining space up between its child elements (giving them each the same amount of extra space). Elements should render fine if they are given more space than they wanted, but if you give them less you will start to see glitches.

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

If you want to be able to scroll the whole thing then I am afraid things will be quite a bit more difficult, because the ScrollViewer gives you an infinite amount of space to work with which will put you in the same position as the child elements were originally. In this situation you might want to create a new property on your new panel which lets you specify the viewport size, you should be able to bind this to the ScrollViewer's size. Ideally you would implement IScrollInfo, but that starts to get complicated if you are going to implement all of it properly.

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

回答by rcabr

An alternative method is to use a Grid with one column and nrows. Set all the rows heights to Auto, and the bottom-most row height to 1*.

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

I prefer this method because I've found Grids have better layout performance than DockPanels, StackPanels, and WrapPanels. But unless you're using them in an ItemTemplate (where the layout is being performed for a large number of items), you'll probably never notice.

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

回答by Dvor_nik

You can use SpicyTaco.AutoGrid- a modified version of StackPanel:

您可以使用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>

First button will be fill.

第一个按钮将被填充。

You can install it via NuGet:

您可以通过 NuGet 安装它:

Install-Package SpicyTaco.AutoGrid

I recommend taking a look at SpicyTaco.AutoGrid. It's very useful for forms in WPF instead of DockPanel, StackPaneland Gridand solve problem with stretching very easy and gracefully. Just look at readme on GitHub.

我建议看看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>