Как получить элементы управления в WPF для заполнения доступного пространства?

304

Некоторые элементы управления WPF (например, the Button), похоже, с удовольствием занимают все доступное пространство в его контейнере, если вы не укажете высоту, которую он должен иметь.

И некоторые, такие как те, которые мне нужно использовать прямо сейчас, (многострочные) TextBoxи другие, ListBoxпохоже, больше беспокоятся о том, чтобы просто занять место, необходимое для их содержимого, и не более того.

Если вы поместите этих парней в камеру UniformGrid, они расширятся, чтобы соответствовать доступному пространству. Однако UniformGridслучаи не подходят для всех ситуаций. Что если у вас есть сетка с некоторыми строками, установленными на * высоту, чтобы разделить высоту между собой и другими * строками? Что если у вас есть a, StackPanelи у вас есть a Label, a Listи a Button, как вы можете получить список, который будет занимать все пространство, не занятое меткой и кнопкой?

Я бы подумал, что это действительно будет основным требованием к макету, но я не могу понять, как заставить их заполнить пространство, которое они могли бы (поместить их в a DockPanelи установить для заполнения также, похоже, не работает, так как DockPanelтолько занимает пространство , необходимое его субэлементами).

Изменяемый размер GUI будет довольно ужасно , если вы должны были играть с Height, Width, MinHeight, и MinWidthт.д.

Можете ли вы связать ваше Heightи Widthсвойство ячейки сетки вы занимаете? Или есть другой способ сделать это?

Руна Якобсен
источник
1
UniformGrid удивителен, мой новый тэг goto по умолчанию. Мне понравилась простота Stackpanels (напоминает мне div), но Uniform Grid делает именно то, что мне нужно.
Терренс
Re UniformGrid. Упор делается на униформу. Кажется, что вы не можете регулировать ширину столбца без высоты строки. Это подходит только если каждый кусок контента имеет одинаковый размер. Я заменил свою StackPanel на Grid, и Stretch затем работал так, как я ожидал.
pdschuller
Эта статья помогла мне растянуть текстовые поля.
jpaugh

Ответы:

162

Каждый элемент управления , вытекающие из Panelорудий отличие логики макета , выполненных в Measure()и Arrange():

  • Measure() определяет размер панели и каждого ее потомка
  • Arrange() определяет прямоугольник, в котором отображается каждый элемент управления

Последний ребенок DockPanelзаполняет оставшееся пространство. Вы можете отключить это поведение, установив LastChildсвойство в false.

StackPanelПрошу каждый ребенок для его нужного размера , а затем складывает их. Панель стека вызывает Measure()каждого дочернего элемента с доступным размером, Infinityа затем использует требуемый размер дочернего элемента .

A Gridзанимает все доступное пространство, однако, он установит для каждого ребенка желаемый размер, а затем отцентрирует их в ячейке.

Вы можете реализовать свою собственную логику компоновки, наследуя Panelи затем переопределяя MeasureOverride()и ArrangeOverride().

Смотрите эту статью для простого примера.

user3837
источник
8
Ссылка сейчас мертва
user3690202
6
@ user3690202 Archive.org - твой друг. Ссылка реанимирована.
ruffin
4
Тема все еще существует в MSDN, но ссылка изменилась на: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/…
Андреа Антонангели
2
The last child of the DockPanel fills the remaining spaceЭто был недостающий ключ к моему пониманию. Я всегда думал, что элемент без явного дока заполняет пространство.
Пятнистый
238

Есть также некоторые свойства, которые вы можете установить, чтобы заставить элемент управления заполнять его доступное пространство, если в противном случае он этого не сделал бы. Например, вы можете сказать:

HorizontalContentAlignment="Stretch"

... чтобы заставить содержимое элемента управления растягиваться горизонтально. Или вы можете сказать:

HorizontalAlignment="Stretch"

... чтобы заставить элемент управления растягиваться горизонтально, чтобы заполнить его родительский элемент.

Мэтт Гамильтон
источник
88
Самая печально известная панель, упомянутая во всех этих случаях, - это StackPanel. Он не содержит свойств ContentAlignment, и установка его дочерних элементов на Stretch не будет иметь никакого эффекта внутри сетки размера звезды. Очень расстраивает. Это почти как если бы StackPanel был первым контейнером, который написала команда WPF, и он страдает от этого.
Брент Скули
4
@ Брент - ах! Я застрял при попытке правильно заполнить содержимое моей стековой панели. Спасибо! Я думал, что это было что-то, что я делал очень неправильно.
Эшли Гренон
8
@townsean Stack панель очень ограничена, вы можете получить аналогичное поведение с растяжением, используя UniformGrid и устанавливая либо Строки или Столбцы в 0
ForbesLindesay
2
@ Tuskan360 UniformGrid позволяет только ячейкам иметь одинаковый размер. Я использовал Grid в конце, кажется, работает. Раздражает, как StackPanel не делает то, для чего он, казалось бы, предназначен.
TarkaDaal
4
@TarkaDaal, да, UniformGrid, если все одинакового размера, Grid, если вы хотите указать сложные относительные размеры, стековую панель размером только на основе содержимого и игнорируйте, сколько места доступно.
ForbesLindesay
18

Ну, я понял это сам, сразу после публикации, что является самым смущающим способом. :)

Кажется, что каждый член StackPanel просто заполнит свой минимальный запрошенный размер.

В DockPanel я закрепил вещи в неправильном порядке. Если TextBox или ListBox является единственным закрепленным элементом без выравнивания, или если они добавлены последними, они БУДУТ заполнять оставшееся пространство по желанию.

Я хотел бы увидеть более элегантный способ справиться с этим, но это подойдет.

Руна Якобсен
источник
Я просто хочу указать (на этот старый вопрос!), Что «без выравнивания» здесь ключевая фраза, по крайней мере, для меня.
MikeBaz - MSFT
4

Используйте свойства макета HorizontalAlignment и VerticalAlignment . Они контролируют, как элемент использует пространство, которое он имеет внутри своего родителя, когда доступно больше места, чем требуется элементу.

Например, ширина StackPanel будет равна ширине самого широкого элемента, который он содержит. Таким образом, все более узкие элементы имеют немного избыточного пространства. Свойства выравнивания управляют тем, что делает дочерний элемент с дополнительным пространством.

Значением по умолчанию для обоих свойств является Stretch, поэтому дочерний элемент растягивается, чтобы заполнить все доступное пространство. Дополнительные параметры включают Левый, Центральный и Правый для горизонтального выравнивания и Верхний, Центральный и Нижний для вертикального выравнивания .

urini
источник
31
Если бы это было всегда так, оригинальный вопрос не был бы задан. Возьмите, например, горизонтальную панель стека с меткой и текстовым полем. Справа от TextBox есть дополнительное место. TextBox установлен на Auto width. Установка Stretch для HorizontalAlignment не позволит TextBox заполнить оставшееся пространство.
Брент Скули
Ничто не всегда верно, но этот ответ работает для моих нужд: DockPanel, Image.
алехро