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

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

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

    <MyFillingTabControl />
</DockPanel>

Ответ 3

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

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

  <Ribbon Grid.Row="0" />

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

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

Ответ 4

Я попробовал много методов здесь, но не могу решить свою проблему. (Заполните другое управление под контролем)

Пока я не нашел it

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