Table of Contents

Компоновка

Компоновка решает, где находится каждый элемент и какого он размера. В каждом кадре, где что-то изменилось, IcyUI спрашивает каждый элемент, какого размера он хочет быть, а затем выдаёт ему прямоугольник для заполнения. Панели решают, как дочерние элементы делят их место; размер, отступы и выравнивание каждого дочернего элемента решают, где он окажется в доставшейся ему части.

Сначала измерение, потом размещение

Компоновка выполняется в два прохода, от Canvas вниз:

  1. Измерение (measure): каждый элемент сообщает желаемый размер, исходя из своего содержимого (текста, изображения, дочерних элементов) и собственных свойств размера.
  2. Размещение (arrange): каждый родитель выдаёт каждому дочернему элементу прямоугольник. Дочерний элемент располагается в нём согласно своим отступам и выравниванию и размещает собственных потомков.

Изменение свойства, влияющего на размер (текста, размера шрифта, отступов, дочерних элементов), помечает элемент для нового измерения; в следующем кадре он компонуется заново. Вызывать компоновку самостоятельно не нужно.

Размер

Свойство Значение
Width / Height Фиксированный размер. По умолчанию не задан (NaN), что означает «по содержимому или по выданному месту».
MinWidth / MaxWidth (и высоты) Пределы итогового размера элемента.
Margin Внешний отступ: место снаружи элемента, между ним и соседями или родителем.
Padding Внутренний отступ: место внутри элемента, между его рамкой и содержимым.

Thickness записывается в целых единицах: "8" (все стороны), "8,4" (слева/справа, сверху/снизу) или "8,4,8,0" (слева, сверху, справа, снизу).

Выравнивание

Внутри выданного прямоугольника элемент располагается согласно HorizontalAlignment (Left, Center, Right, Stretch) и VerticalAlignment (Top, Center, Bottom, Stretch). Stretch заполняет прямоугольник, если не задан Width/Height; остальные значения подгоняют размер под содержимое.

<!-- Each child gets the space its parent offers; its size, margin and alignment decide where it sits in it. -->
<StackPanel Orientation="Vertical" Width="320" Padding="8">
  <Button HorizontalAlignment="Left" Margin="0,0,0,8">Left</Button>
  <Button Margin="0,0,0,8">Centered (the theme's default for buttons)</Button>
  <Button HorizontalAlignment="Stretch" Margin="0,0,0,8">Stretch</Button>
  <Button HorizontalAlignment="Right" MinWidth="160">Right, at least 160 wide</Button>
</StackPanel>

По умолчанию элементы растягиваются. Тема по умолчанию центрирует кнопки, чтобы кнопка, добавленная прямо на Canvas, не закрывала игру; локальный HorizontalAlignment="Stretch" у кнопки снова заставляет её заполнить свою ячейку.

Панели

Панель Как делит своё место
StackPanel Дочерние элементы друг за другом, в столбец или в строку.
Grid Строки и столбцы размера Auto, в пикселях или долями (*, 2*); дочерние элементы занимают ячейки.
WrapGrid Одинаковые ячейки в строках с переносом, для инвентаря.
ScrollViewer Содержимое больше самой панели, с прокруткой.
SplitPane Две части с перетаскиваемым разделителем.

Свойства каждой панели описаны на страницах Панели и Прокрутка. Список (ListBox или WrapGrid) вне ScrollViewer подстраивает размер под свои элементы.

Масштаб

Компоновка работает в единицах интерфейса. При отрисовке Canvas умножает их на свой масштаб (DPI дисплея или опорное разрешение), поэтому панель шириной 200 единиц сохраняет физический размер и на 4K-экране. См. DPI и масштабирование.

Типичные ошибки

  • Незаданные пределы равны NaN. В собственных элементах управления не передавайте Width или MinWidth прямо в Math.Min, Math.Max или float.Clamp: граница NaN даёт NaN. Сначала проверьте float.IsNaN.
  • Растянутому элементу в родителе, подстраивающемся под содержимое, некуда растягиваться. В строке StackPanel Stretch вдоль строки означает «по содержимому»; задайте элементу Width или используйте Grid со столбцом *.
  • Скрытые элементы сохраняют своё место. См. Canvas, хост и дерево элементов.

См. также