Як використовувати DockStyle.Fill для стандартних елементів керування у WPF?


92

Мене використовують із форм Windows, що я створюю панель, розміщую елементи керування всередині неї і надаю їм DockStyle.Fill максимальний розмір для оточуючої панелі.

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

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

Відповіді:


181

WPF-еквівалент WinForms 'DockStyle.Fill:

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>

Крім того, будь-який рядок або стовпець сітки, висота якого має значення "Авто", аналогічним чином стискає вміст у цьому напрямку.

Ось приклади контейнерів, які не здавлюють своїх дітей:

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


Я залишив тут досить складне нове питання, пов’язане з макетом . Прочитавши вашу відповідь тут, я думаю, ви можете це зрозуміти. Вітання
Берріл

7
Відмінна відповідь! Я хотів би якось дати тобі бонусні бали. :)
Jim Raden

@Jim Raden: Ви можете додати нагороду до цього питання і призначити очки Рей Бернсу;)
citronas

1
Додаткова примітка для майбутніх читачів: вона не буде оновлюватися в поданні дизайну, поки ви не перекомпілюєте.
Девід

"<Button Content =" Чому я не заповнюю вікно? "Width =" 200 "Height =" 20 "/>" зламав мене! XD
Джек Мороз

7

Ви можете робити те, що хочете, просто сказавши, DockPanel LastChildFill="True"а потім переконавшись, що ви хочете бути наповнювачем - це насправді остання дитина!

Сітка - це звір макету, який ви можете змусити робити майже все, але DockPanel, як правило, є правильним вибором для вашої найвіддаленішої панелі макета. Ось приклад psuedocode:

<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 = .." до дочірніх елементів керування сітки, які вони призначають рядкам сітки. Тоді сітка буде визначати розмір своїх дітей, як це визначено визначеннями рядків.


Йде в правильному напрямку, дякую. Мені вдалося вставити сітку, але тепер мені потрібно сказати TabControl, що вона повинна використовувати весь розмір, який все ще доступний? Як я можу цього досягти?
citronas

Вам потрібно додати атрибут "Grid.Row" для TabControl і надати відповідному визначенню рядка висоту "*" - як показано в прикладі.
andyp

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.