Как использовать DockStyle.Fill для стандартных элементов управления в WPF?


92

Я использую формы Windows: я создаю панель, помещаю в нее элементы управления и передаю им DockStyle.Fillмаксимальный размер для окружающей панели.

В WPF я хочу иметь то же самое. У меня есть TabControl, и я хочу, чтобы его размер занимал как можно большую часть формы. У меня есть ленточный элемент управления (RibbonControlsLibrary), и я хочу, чтобы остальная часть формы была заполнена элементом TabControl максимального размера.

(Я не хочу закреплять элементы управления, такие как стыковка в Visual Studio, просто старые механизмы стыковки)

Ответы:


181

WPF-эквивалент DockStyle.Fill WinForms:

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>

Просто удалите атрибуты Ширина и Высота:

<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>

Кроме того, любая строка или столбец сетки с высотой «Авто» аналогичным образом сжимает свое содержимое в этом направлении.

Вот некоторые примеры контейнеров, которые не сжимают своих детей:

  • ContentControls никогда не сжимает своих дочерних элементов (включая 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.


Я оставил здесь довольно сложный вопрос, связанный с новым макетом . Прочитав ваш ответ здесь, я думаю, вы сможете понять это. Cheers
Berryl

7
Отличный ответ! Хотел бы я как-нибудь дать вам бонусные баллы. :)
Джим Раден

@Jim Raden: Вы можете добавить награду к этому вопросу и назначить очки Рэю Бёрнсу;)
citronas

1
Примечание для будущих читателей: он не будет обновляться в представлении дизайна, пока вы не перекомпилируете.
Дэвид

"<Button Content =" Почему я не заполняю окно? "Width =" 200 "Height =" 20 "/>" взбесило меня! XD
Джек Фрост

7

Вы можете делать то, что хотите, просто сказав, DockPanel LastChildFill="True"а затем убедившись, что вы хотите, чтобы наполнитель был последним ребенком!

Сетка - это чудовище макета, с которым можно делать практически все, но DockPanel обычно является правильным выбором для самой внешней панели макета. Вот пример псевдокода:

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

    <MyFillingTabControl />
</DockPanel>

5

просто оберните элементы управления в сетку из двух строк. Сетка будет автоматически использовать все предоставленное ей пространство, и вы можете определить строки так, чтобы они занимали все оставшееся пространство, задав им высоту «*». Первая строка в моем примере (Высота = "Авто") займет столько места, сколько нужно для ленты. Надеюсь, это поможет.

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

  <Ribbon Grid.Row="0" />

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

Добавляя атрибут «Grid.Row = ..» к дочерним элементам управления сетки, они назначаются строкам сетки. Затем сетка будет определять размер дочерних элементов в соответствии с определениями строк.


Идет в правильном направлении, спасибо. Мне удалось вставить сетку, но теперь мне нужно сказать TabControl, что он должен использовать весь размер, который еще доступен? Как я могу этого добиться?
citronas 09

Вам необходимо добавить атрибут «Grid.Row» для TabControl и присвоить соответствующему определению строки высоту «*» - как показано в примере.
Andyp 09

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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.