如何让StackPanel's子填充最大空间向下?

我只是希望左边有流动文本,右边有一个帮助框。

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

如果你去掉下面的外层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>

答:

谢谢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>
407277 次浏览

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

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>

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

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

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

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

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

你可以使用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中的表单非常有用,而不是DockPanelStackPanelGrid,并且非常简单而优雅地解决问题。看看GitHub上的readme就知道了。

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


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


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