如何在WPF中将DockStyle.Fill用于标准控件?


92

我使用的是Windows窗体,我创建了一个面板,将控件放置在其中,并赋予它们DockStyle.Fill最大尺寸以适应周围的面板。

在WPF中,我希望拥有相同的内容。我有一个TabControl,并且我希望它的大小能填充尽可能多的表单。我有一个功能区控件(RibbonControlsLibrary),并希望表格的其余部分以最大尺寸的TabControl填充。

(我不想将控件停靠在Visual Studio中,例如停靠,只是旧的停靠机制)

Answers:


183

WinForms的DockStyle.Fill的WPF等效项是:

HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

这是几乎所有控件的默认设置,因此,一般而言,您无需执行任何操作即可让WPF控件填充其父容器:它们会自动执行。对于所有不将子级压缩到最小大小的容器来说都是如此。

常见错误

现在,我将解释一些HorizontalAlignment="Stretch" VerticalAlignment="Stretch"无法按预期工作的常见错误。

1.明确的高度或宽度

一个常见的错误是为控件明确指定宽度或高度。因此,如果您有:

<Grid>
  <Button Content="Why am I not filling the window?" Width="200" Height="20" />
  ...
</Grid>

只需删除Width和Height属性:

<Grid>
  <Button Content="Ahhh... problem solved" />
  ...
</Grid>

2.包含面板将控件压缩到最小尺寸

另一个常见的错误是包含面板会紧紧挤压控件。例如,垂直的StackPanel始终将垂直压缩的内容尽可能减小:

<StackPanel>
  <Button Content="Why am I squished flat?" />
</StackPanel>

转到另一个面板,您将很高兴:

<DockPanel>
  <Button Content="I am no longer squished." />
</DockPanel>

同样,高度为“自动”的任何网格行或列都将类似地沿该方向压缩其内容。

不会挤压孩子的容器的一些示例是:

  • ContentControl绝不挤压其子级(包括Border,Button,CheckBox,ScrollViewer等)
  • 具有单个行和列的网格
  • 具有“ *”大小的行和列的网格
  • DockPanel不会挤压最后一个孩子
  • TabControl不会挤压其内容

确实会挤压孩子的容器的一些示例是:

  • StackPanel沿其方向挤压
  • 具有“自动”大小的行或列的网格朝该方向挤压
  • DockPanel将除最后一个孩子以外的所有孩子挤向其停靠方向
  • TabControl压缩其标题(选项卡上显示的内容)

3.更明确的高度或宽度

令人惊讶的是,我看到Grid或DockPanel给出了明确的高度和宽度,如下所示:

<Grid Width="200" Height="100">
  <Button Content="I am unnecessarily constrainted by my containing panel" />
</Grid>

通常,您永远都不想给任何面板明确的高度或宽度。诊断布局问题时,我的第一步是删除我可以找到的所有显式“高度”或“宽度”。

4.窗口不应该是SizeToContent

当您使用SizeToContent时,您的内容将被压缩到最小大小。在许多应用中,这非常有用,并且是正确的选择。但是,如果您的内容没有“自然”大小,则可能要忽略SizeToContent。


在这里留下了一个与新布局有关的相当复杂的问题。在阅读完您的答案后,我认为您可以解决它。干杯
贝里2010年

7
很好的答案!希望我能以某种方式给您加分。:)
Jim Raden

@吉姆·拉登(Jim Raden):您可以在这个问题上添加赏金,并将积分分配给雷·伯恩斯(Ray Burns);)
香茅油(Citronas

1
将来的读者请注意:在重新编译之前,它不会在设计视图中更新。
戴维(David)

“ <Button Content =”我为什么不填充窗口?“ Width =” 200“ Height =” 20“ />”吓到我了!XD
Jack Frost 2015年

7

您可以说出自己想要做的DockPanel LastChildFill="True",然后确保您想要成为填充者的实际上是最后一个孩子!

网格是您可以做大多数事情的布局的野兽,但是DockPanel通常是最外面的布局面板的正确选择。这是一个伪代码示例:

<DockPanel LastChildFill="True">
    <MyMenuBar DockPanel.Dock="Top"/>
    <MyStatus DockPanel.Dock="Bottom"/>

    <MyFillingTabControl />
</DockPanel>

5

只需将控件包装在两行网格中即可。网格将自动使用分配给它的所有空间,您可以通过将行的高度设置为“ *”来定义要占用的剩余空间。我的示例中的第一行(Height =“ Auto”)将占用功能区所需的空间。希望能有所帮助。

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Ribbon Grid.Row="0" />

  <TabPage Grid.Row="1" />
</Grid>

通过将“ Grid.Row = ..”属性添加到网格的子控件,它们将被分配给网格的行。然后,网格将按照行定义的大小调整其子级。


朝正确的方向前进,谢谢。我设法插入了Grid,但是现在我需要告诉TabControl它应该使用仍然可用的所有大小?我该如何实现?
香茅油

您需要为TabControl添加“ Grid.Row”属性,并将对应的行定义的高度设置为“ *”,如示例所示。
andyp 2010年

0

我在这里尝试了很多方法,但无法解决我的问题。(在控件中填充其他控件)

直到我找到

<Name_Control Height="auto" Width="auto"/>
//default
//HorizontalAlignment="Stretch" 
//VerticalAlignment="Stretch"

例:

//UserControl:
<UserControl Name="UC_Test" Height="auto" Width="auto" />
//Grid: 
<Grid Name="Grid_test" Grid.ColumnSpan="2" Grid.Row="2" />
//Code: 
Grid_test.Children.Add(UC_Test);

易于设计

<UserControl Name="UC_Test" Height="100" Width="100" />
//Code
Grid_test.Children.Add(UC_Test);
UC_Test.Width = Double.NaN;
UC_Test.Height = Double.NaN;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.