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

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

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

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

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

Изменяемый размер графического интерфейса был бы ужасен, если бы вам пришлось играть с Height, Width, MinHeight, MinWidth и т. Д.

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


person Rune Jacobsen    schedule 30.08.2008    source источник
comment
UniformGrid великолепен, мой новый тег goto по умолчанию. Мне понравилась простота Stackpanels (напоминает мне div), но Uniform Grid делает именно то, что мне нужно.   -  person Terrance    schedule 12.08.2012
comment
Re UniformGrid. Акцент делается на униформу. Кажется, вы не можете регулировать ширину столбцов и высоту строк. Это подходит только в том случае, если все фрагменты контента имеют одинаковый размер. Я заменил StackPanel сеткой, и Stretch работал так, как я ожидал.   -  person pdschuller    schedule 27.03.2018
comment
Эта статья помогла мне растянуть текстовые поля.   -  person jpaugh    schedule 12.08.2019


Ответы (4)


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

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

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

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

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

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

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

person user3837    schedule 31.08.2008
comment
@ user3690202 Archive.org - ваш друг. Ссылка реанимирована. - person ruffin; 18.06.2016
comment
Тема все еще существует в MSDN, но ссылка изменилась на эту: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/ - person Andrea Antonangeli; 25.06.2017
comment
The last child of the DockPanel fills the remaining space: это был недостающий ключ к моему пониманию. Я всегда думал, что элемент без явного Dock заполняет пространство. - person Spotted; 29.07.2019

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

HorizontalContentAlignment="Stretch"

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

HorizontalAlignment="Stretch"

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

person Matt Hamilton    schedule 31.08.2008
comment
Самая известная панель, упоминаемая во всех этих случаях, - это StackPanel. Он не содержит свойств ContentAlignment, и установка его дочерних элементов на Stretch не будет иметь никакого эффекта внутри сетки размером со звезду. Очень неприятно. Это похоже на то, как если бы StackPanel был первым контейнером, написанным командой WPF, и от этого страдает. - person Brent Schooley; 25.04.2009
comment
@ Брент - ааа! Я застрял, пытаясь правильно заполнить содержимое моей панели стека. Благодарность! Я думал, что это просто что-то, что я делал очень неправильно. - person Ashley Grenon; 21.10.2010
comment
Панель @townsean Stack очень ограничена, вы можете получить аналогичное поведение с растяжкой, используя UniformGrid и установив для Rows или Columns значение 0 - person ForbesLindesay; 04.08.2011
comment
@ Tuskan360 UniformGrid позволяет ячейкам быть только одного размера. В конце концов, я использовал сетку, похоже, работает. Раздражает, что StackPanel не делает того, для чего он, казалось бы, предназначен. - person TarkaDaal; 15.05.2012
comment
@TarkaDaal yeh, UniformGrid, если все одинакового размера, Grid, если вы хотите указать сложные относительные размеры, панель стека только размером в зависимости от содержимого и игнорирование доступного места. - person ForbesLindesay; 15.05.2012
comment
Bang, Bulls eye :) Большое спасибо, именно тот фрагмент кода, который я искал все время! - person Chandraprakash; 14.08.2020

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

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

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

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

person Rune Jacobsen    schedule 30.08.2008
comment
Я просто хочу указать (по этому старому вопросу!), Что без согласования здесь ключевая фраза, по крайней мере, для меня. - person MikeBaz - MSFT; 26.03.2013

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

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

Значение по умолчанию для обоих свойств - Stretch, поэтому дочерний элемент растягивается, чтобы заполнить все доступное пространство. Дополнительные параметры: «Слева», «По центру» и «Справа» для HorizontalAlignment и «Сверху», «По центру» и «Снизу» для VerticalAlignment.

person urini    schedule 31.08.2008
comment
Если бы это всегда было правдой, исходный вопрос не задавался бы. Возьмем, например, горизонтальную панель StackPanel с меткой и текстовым полем. Справа от текстового поля есть дополнительное пространство. TextBox имеет значение Автоматическая ширина. Установка Stretch для HorizontalAlignment не заставит TextBox заполнить оставшееся пространство. - person Brent Schooley; 25.04.2009
comment
Ничто не всегда верно, но этот ответ подходит для моих нужд: DockPanel, Image. - person alehro; 21.01.2020