如何让 StackPanel 的孩子向下填充最大空间?
Posted
技术标签:
【中文标题】如何让 StackPanel 的孩子向下填充最大空间?【英文标题】:How to get StackPanel's children to fill maximum space downward? 【发布时间】:2010-10-08 19:39:52 【问题描述】:我只想在左侧显示流畅的文本,在右侧显示帮助框。
帮助框应该一直延伸到底部。
如果你去掉下面的外部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>
【问题讨论】:
修复了格式 - 它不喜欢直接从列表转到代码 你可以让 GroupBox 自行拉伸吗?如果是这样,开始一个一个地添加你的父元素,直到你找出哪个破坏了布局。 RoBorg:很高兴知道,这让我很困惑,谢谢 谢谢。使用您的答案,我能够使用 2 个嵌套的 DockPanel 来解决我非常相似的问题! 【参考方案1】:您可以使用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 中的表单而不是 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>
【讨论】:
这个应该在最上面,很有用,非常感谢! 别忘了加上 xmlns:st="schemas.spicytaco.io"【参考方案2】:听起来你想要一个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>
【讨论】:
太棒了!我花了最后一个小时试图弄清楚如何让 StackPanel 做到这一点。从现在开始,我将首先在此处查找我的 WPF(和其他)信息。 我无法相信我花了多少时间试图让 StackPanels 做我想做的事。感谢分享! DockPanel 是我一直想要的。 似乎没有平板电脑的停靠面板。 telerik.com/forums/following-blog-post-and-comparison 没有适用于 Windows 应用商店应用的停靠面板。 现在都是通用应用,通用应用还不支持 DockPanel?【参考方案3】:发生这种情况的原因是因为堆栈面板测量每个子元素,正无穷大作为它正在堆叠元素的轴的约束。子控件必须返回它们想要的大小(正无穷大不是来自任一轴的MeasureOverride 的有效返回),因此它们返回适合所有内容的最小尺寸。他们无法知道自己真正需要填满多少空间。
如果您的视图不需要具有滚动功能并且上面的答案不适合您的需求,我建议您实现自己的面板。您可能可以直接从 StackPanel 派生,然后您需要做的就是更改 ArrangeOverride 方法,以便它在其子元素之间划分剩余空间(给它们每个相同数量的额外空间)。如果给元素的空间比他们想要的多,它们应该可以很好地渲染,但如果你给它们的空间少,你就会开始看到故障。
如果您希望能够滚动整个内容,那么恐怕事情会变得更加困难,因为 ScrollViewer 为您提供了无限的工作空间,这将使您处于与最初是子元素。在这种情况下,您可能希望在新面板上创建一个新属性,让您指定视口大小,您应该能够将其绑定到 ScrollViewer 的大小。理想情况下,您应该实现 IScrollInfo,但如果您要正确实现所有这些,事情就会变得复杂。
【讨论】:
+1,我会给你更多,但只允许 1,你的第一段指出了许多 Microsoft 页面未能做到的事情,即为什么无穷大可以作为高度/宽度出现以及事实您不能依赖从 MeasureOverride 返回 availableSize。 Grid 中的 StackPanel 轻松解决了他相当普遍的需求。如有必要,可以将底部位放在 ScrollViewer 中。自 2006 年以来,我一直在做 WPF,并且只需要做一次自定义面板。我认为鼓励额外的复杂性不是一个好主意。 @ChrisBordeman 我不确定我是否理解网格内的堆栈面板如何解决问题。这个想法是让堆栈面板中的一个或多个子元素伸展以填充可用空间。将堆栈面板放在网格内并不能做到这一点吗?【参考方案4】:另一种方法是使用一列和 n 行的 Grid。将所有行高设置为Auto
,将最底部的行高设置为1*
。
我更喜欢这种方法,因为我发现网格比 DockPanel、StackPanel 和 WrapPanel 具有更好的布局性能。但是,除非您在 ItemTemplate 中使用它们(对大量项目执行布局),否则您可能永远不会注意到。
【讨论】:
对我来说是最好的解决方案。有了这个,就可以定义一个以上的增长行以上是关于如何让 StackPanel 的孩子向下填充最大空间?的主要内容,如果未能解决你的问题,请参考以下文章
有两个孩子的父 div。即使没有显示另一个孩子,也总是让一个孩子填充父母?
如何让 ScrollViewer 在 StackPanel 中工作?