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
How to get StackPanel's children to fill maximum space downward?
提问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 StackPanel
below 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 GroupBox
to 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 DockPanel
instead of StackPanel
cleared it up. In general, I find myself using DockPanel
more 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 StackPanel
where the final element uses up all the remaining space. But why not use a DockPanel
? Decorate the other elements in the DockPanel
with DockPanel.Dock="Top"
, and then your help control can fill the remaining space.
听起来你想要一个StackPanel
最终元素用完所有剩余空间的地方。但为什么不使用DockPanel
?装修中的其他元素DockPanel
与DockPanel.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 DockPanel
available (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
, StackPanel
and Grid
and solve problem with stretching very easy and gracefully. Just look at readme on GitHub.
我建议看看SpicyTaco.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>