Como obter controles no WPF para preencher o espaço disponível?
-
09-06-2019 - |
Pergunta
Alguns controles WPF (como o Button
) parecem consumir alegremente 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 preciso usar agora, o (multiline) TextBox
e a ListBox
parecem mais preocupados em ocupar apenas o espaço necessário para acomodar seu conteúdo e nada mais.
Se você colocar esses caras em uma cela em um UniformGrid
, eles serão expandidos para caber no espaço disponível.No entanto, UniformGrid
instâncias não são adequadas para todas as situações.E se você tiver uma grade com algumas linhas definidas com altura * para dividir a altura entre ela e outras linhas *?E se você tiver um StackPanel
e você tem um Label
, a List
e um Button
, como você pode fazer com que a lista ocupe todo o espaço não ocupado 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 poderiam (colocando-os em um DockPanel
e configurá-lo para preencher também não funciona, ao que parece, já que o DockPanel
ocupa apenas o espaço necessário para seus subcontroles).
Uma GUI redimensionável seria horrível se você tivesse que brincar com Height
, Width
, MinHeight
, MinWidth
etc.
Você pode vincular seu Height
e Width
propriedades para a célula da grade que você ocupa?Ou existe outra maneira de fazer isso?
Solução
Cada controle derivado de Panel
implementa lógica de layout distinta executada em Measure()
e Arrange()
:
Measure()
determina o tamanho do painel e de cada um de seus filhosArrange()
determina o retângulo onde cada controle é renderizado
O último filho do DockPanel
preenche o espaço restante.Você pode desativar esse comportamento configurando o LastChild
propriedade para false
.
O StackPanel
pede a cada criança o tamanho desejado e depois empilha-os.O painel de pilha chama Measure()
em cada criança, com um tamanho disponível de Infinity
e depois usa o tamanho desejado da criança.
A Grid
ocupa todo o espaço disponível, porém, irá definir cada filho no tamanho desejado e depois centralizá-los na célula.
Você pode implementar sua própria lógica de layout derivando de Panel
e então substituindo MeasureOverride()
e ArrangeOverride()
.
Ver Este artigo para um exemplo simples.
Outras dicas
Existem também algumas propriedades que você pode definir para forçar um controle a preencher seu espaço disponível quando, de outra forma, não o faria.Por exemplo, você pode dizer:
HorizontalContentAlignment="Stretch"
...para forçar o conteúdo de um controle a se esticar horizontalmente.Ou você pode dizer:
HorizontalAlignment="Stretch"
...para forçar o próprio controle a se esticar horizontalmente para preencher seu pai.
Bem, eu mesmo descobri, logo após postar, que é a forma mais embaraçosa.:)
Parece que cada membro de um StackPanel simplesmente preencherá o tamanho mínimo solicitado.
No DockPanel, encaixei as coisas na ordem errada.Se TextBox ou ListBox for o único item encaixado sem alinhamento, ou se forem os últimos adicionados, eles preencherão o espaço restante conforme desejado.
Eu adoraria ver um método mais elegante de lidar com isso, mas servirá.
Use o Alinhamento horizontal e Alinhamento vertical propriedades de layout.Eles controlam como um elemento usa o espaço que possui 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 possuem 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 é esticado para preencher todo o espaço disponível.As opções adicionais incluem Esquerda, Centro e Direita para Alinhamento horizontal e Superior, Central e Inferior para Alinhamento vertical.