Como obter controles no WPF para preencher o espaço disponível?

304

Alguns controles WPF (como o Button) parecem consumir todo o espaço disponível em seu contêiner, se você não especificar a altura que ele deve ter.

E alguns, como os que eu preciso usar agora, os (multilinhas) TextBoxe os ListBoxparecem mais preocupados em apenas ocupar o espaço necessário para ajustar seu conteúdo, e não mais.

Se você colocar esses caras em uma célula em um UniformGrid, eles serão expandidos para caber no espaço disponível. No entanto, as UniformGridinstâncias não são adequadas para todas as situações. E se você tiver uma grade com algumas linhas definidas como * height para dividir a altura entre si e outras * linhas? E se você tiver um StackPanele você tiver um Label, um Liste um Button, como conseguir que a lista ocupe todo o espaço não consumido pelo rótulo e pelo botão?

Eu acho que isso seria realmente um requisito básico de layout, mas não consigo descobrir como fazê-los preencher o espaço que eles poderiam (colocá-los em DockPanele defini-los para preencher também não funciona, ao que parece, pois o DockPanelúnico ocupa o espaço necessário para seus 'subcontroles).

A GUI redimensionável seria muito horrível se você tivesse que jogar com Height, Width, MinHeight, MinWidthetc.

Você pode vincular suas propriedades Heighte Widthà célula da grade que ocupa? Ou existe outra maneira de fazer isso?

Rune Jacobsen
fonte
1
UniformGrid é incrível, Minha nova tag padrão de goto. Gostei da simplicidade do Stackpanels (me lembra uma div), mas o Uniform Grid faz exatamente o que eu preciso.
Terrance
Re UniformGrid. A ênfase está no uniforme. Parece que você não pode ajustar as larguras das colunas sem alturas de linha. Só é adequado se cada conteúdo tiver o mesmo tamanho. Substituí meu StackPanel por um Grid, e o Stretch funcionou como eu esperava.
Pdschuller # 27/18
Este artigo me ajudou a ampliar as caixas de texto.
jpaugh

Respostas:

162

Cada controle derivado Panelimplementa uma lógica de layout distinta executada em Measure()e Arrange():

  • Measure() determina o tamanho do painel e cada um de seus filhos
  • Arrange() determina o retângulo onde cada controle é processado

O último filho do DockPanelpreenche o espaço restante. Você pode desativar esse comportamento, definindo a LastChildpropriedade como false.

Ele StackPanelpede a cada criança o tamanho desejado e as empilha. O painel da pilha chama Measure()cada criança, com um tamanho disponível de Infinitye, em seguida, usa o tamanho desejado da criança.

A Gridocupa todo o espaço disponível, no entanto, ele definirá cada criança para o tamanho desejado e as centralizará na célula.

Você pode implementar sua própria lógica de layout, derivando Panele substituindo MeasureOverride()e ArrangeOverride().

Veja este artigo para um exemplo simples.

user3837
fonte
8
Link agora está morto
user3690202
6
@ user3690202 Archive.org é seu amigo. Link reanimado.
Ruffin
4
O tema ainda existe no MSDN, mas o link alterado para isso: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/...
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: esta foi a chave que faltava ao meu entendimento. Sempre achei que o elemento sem Dock explícito preenchia o espaço.
manchado
238

Também há algumas propriedades que você pode definir para forçar um controle a preencher seu espaço disponível quando, caso contrário, não o faria. Por exemplo, você pode dizer:

HorizontalContentAlignment="Stretch"

... para forçar o conteúdo de um controle a esticar horizontalmente. Ou você pode dizer:

HorizontalAlignment="Stretch"

... forçar o próprio controle a esticar horizontalmente para preencher seu pai.

Matt Hamilton
fonte
88
O painel mais notório mencionado em todos esses casos é o StackPanel. Ele não contém propriedades ContentAlignment e a definição de seus filhos como Stretch não terá efeito dentro de uma grade em tamanho de estrela. Muito frustrante. É quase como se o StackPanel fosse o primeiro contêiner que a equipe do WPF escreveu e sofra por isso.
Brent Schooley
4
@Brent - ahh! Estou tentando manter o conteúdo do meu stackpanel preenchido corretamente. obrigado! Eu pensei que era apenas algo que eu estava fazendo muito errado.
precisa
8
@townsean painel Stack é muito limitado, você pode obter um comportamento semelhante com alongamento usando um UniformGrid e definindo tanto linhas ou colunas para 0
ForbesLindesay
2
@ Tuskan360 UniformGrid apenas permite que as células tenham o mesmo tamanho. Eu usei uma grade no final, parece funcionar. Irritante como o StackPanel não faz o que aparentemente foi projetado.
TarkaDaal
4
@TarkaDaal yeh, UniformGrid se tudo tiver o mesmo tamanho, Grid se você quiser especificar tamanhos relativos complexos, empilhar o painel para apenas o tamanho com base no conteúdo e ignorar a quantidade de espaço disponível.
ForbesLindesay
18

Bem, eu mesmo descobri, logo após postar, qual é a maneira mais embaraçosa. :)

Parece que todos os membros de um StackPanel simplesmente preencherão o tamanho mínimo solicitado.

No DockPanel, encaixei as coisas na ordem errada. Se o TextBox ou o ListBox for o único item ancorado sem alinhamento, ou se eles forem os últimos adicionados, preencherão o espaço restante conforme desejado.

Eu adoraria ver um método mais elegante de lidar com isso, mas funcionará.

Rune Jacobsen
fonte
Eu só quero ressaltar (nesta pergunta antiga!) Que "sem alinhamento" é uma frase-chave aqui, pelo menos era para mim.
MikeBaz - MSFT 26/03
4

Use as propriedades de layout HorizontalAlignment e VerticalAlignment . Eles controlam como um elemento usa o espaço que tem dentro de seu pai quando há mais espaço disponível do que o exigido pelo elemento.

A largura de um StackPanel, por exemplo, será tão larga quanto o elemento mais largo que ele contém. Portanto, todos os elementos mais estreitos têm um pouco de espaço em excesso. As propriedades de alinhamento controlam o que o elemento filho faz com o espaço extra.

O valor padrão para ambas as propriedades é Stretch, portanto, o elemento filho é estendido para preencher todo o espaço disponível. As opções adicionais incluem Esquerda, Central e Direita para HorizontalAlignment e Superior, Central e Inferior para VerticalAlignment .

urini
fonte
31
Se isso sempre fosse verdade, a pergunta original não teria sido feita. Tome, por exemplo, um StackPanel horizontal com um Label e um TextBox. Há espaço extra à direita da caixa de texto. O TextBox está definido como Largura automática. Definir a extensão para HorizontalAlignment não fará com que o TextBox preencha o espaço restante.
Brent Schooley
Nada é sempre verdadeiro, mas esta resposta funciona para minhas necessidades: DockPanel, Image.
alehro 21/01