Como usar DockStyle.Fill para controles padrão no WPF?

92

Estou acostumado com o Windows Forms, que eu crio um painel, coloco controles dentro dele e dou-lhes o DockStyle.Fillmáximo de tamanho para o painel ao redor.

No WPF quero ter o mesmo. Eu tenho um TabControl e quero que seu tamanho preencha o máximo possível do formulário. Eu tenho um controle da faixa de opções (RibbonControlsLibrary) e quero que o resto do formulário seja preenchido com o TabControl no tamanho máximo.

(Não quero encaixar controles como no Visual Studio, apenas mecanismos de encaixe antigos)

citronas
fonte

Respostas:

183

O equivalente WPF de DockStyle.Fill do WinForms é:

HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Este é o padrão para quase controles, portanto, em geral, você não precisa fazer nada para que um controle WPF preencha seu contêiner pai : eles fazem isso automaticamente. Isso é verdade para todos os recipientes que não comprimem seus filhos até o tamanho mínimo.

Erros comuns

Vou agora explicar vários erros comuns que impedem o HorizontalAlignment="Stretch" VerticalAlignment="Stretch"funcionamento conforme o esperado.

1. Altura ou largura explícita

Um erro comum é especificar explicitamente uma largura ou altura para um controle. Então, se você tem isso:

<Grid>
  <Button Content="Why am I not filling the window?" Width="200" Height="20" />
  ...
</Grid>

Basta remover os atributos de largura e altura:

<Grid>
  <Button Content="Ahhh... problem solved" />
  ...
</Grid>

2. O painel que contém o controle aperta o tamanho mínimo

Outro erro comum é fazer com que o painel de contenção aperte o seu controle o máximo possível. Por exemplo, um StackPanel vertical sempre comprimirá seu conteúdo verticalmente tão pequeno quanto possível:

<StackPanel>
  <Button Content="Why am I squished flat?" />
</StackPanel>

Mude para outro painel e você estará pronto para prosseguir:

<DockPanel>
  <Button Content="I am no longer squished." />
</DockPanel>

Além disso, qualquer linha ou coluna de grade cuja altura seja "Auto" irá espremer de forma semelhante seu conteúdo nessa direção.

Alguns exemplos de contêineres que não comprimem seus filhos são:

  • ContentControls nunca espremem seus filhos (isso inclui Border, Button, CheckBox, ScrollViewer e muitos outros)
  • Grade com uma única linha e coluna
  • Grade com linhas e colunas de tamanho "*"
  • DockPanel não aperta seu último filho
  • TabControl não comprime seu conteúdo

Alguns exemplos de recipientes que comprimem seus filhos são:

  • StackPanel comprime em sua direção de Orientação
  • Grade com linha ou coluna de tamanho "Auto" comprimida nessa direção
  • DockPanel aperta todos, exceto seu último filho na direção do dock
  • TabControl comprime seu cabeçalho (o que é exibido na guia)

3. Altura ou largura explícita mais para fora

É incrível quantas vezes vejo Grid ou DockPanel com altura e largura explícitas, como esta:

<Grid Width="200" Height="100">
  <Button Content="I am unnecessarily constrainted by my containing panel" />
</Grid>

Em geral, você nunca deseja dar a qualquer painel uma altura ou largura explícita. Minha primeira etapa ao diagnosticar problemas de layout é remover cada altura ou largura explícita que posso encontrar.

4. A janela é SizeToContent quando não deveria ser

Quando você usa SizeToContent, seu conteúdo será reduzido ao tamanho mínimo. Em muitas aplicações, isso é muito útil e é a escolha correta. Mas se o seu conteúdo não tiver um tamanho "natural", você provavelmente desejará omitir SizeToContent.

Ray Burns
fonte
Eu deixei uma questão bastante complexa relacionada ao layout aqui . Depois de ler sua resposta aqui estou pensando que você pode descobrir isso. Saúde
Berryl
7
Excelente resposta! Eu gostaria de poder lhe dar pontos de bônus. :)
Jim Raden
@Jim Raden: Você pode adicionar uma recompensa a esta pergunta e atribuir os pontos a Ray Burns;)
citronas
1
Nota lateral para leitores futuros: ele não será atualizado na visualização do design até que você recompile.
David
"<Button Content =" Por que não estou enchendo a janela? "Width =" 200 "Height =" 20 "/>" me deixou louco! XD
Jack Frost
7

Você pode fazer o que quiser apenas dizendo DockPanel LastChildFill="True"e, em seguida, certificando-se de que o que deseja que seja o preenchedor seja realmente o último filho!

O Grid é a besta de um layout que você pode fazer para quase tudo, mas o DockPanel é geralmente a escolha certa para seu painel de layout externo. Aqui está um exemplo de psuedocode:

<DockPanel LastChildFill="True">
    <MyMenuBar DockPanel.Dock="Top"/>
    <MyStatus DockPanel.Dock="Bottom"/>

    <MyFillingTabControl />
</DockPanel>
Berryl
fonte
5

apenas envolva seus controles em uma grade com duas linhas. A grade usará automaticamente todo o espaço dado a ela e você pode definir as linhas para ocupar todo o espaço deixado, dando-lhes uma altura de "*". A primeira linha do meu exemplo (Height = "Auto") ocupará o espaço necessário para a faixa de opções. Espero que ajude.

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Ribbon Grid.Row="0" />

  <TabPage Grid.Row="1" />
</Grid>

Ao adicionar o atributo "Grid.Row = .." aos controles filhos da grade, eles são atribuídos às linhas da grade. Em seguida, a grade irá dimensionar seus filhos conforme definido pelas definições de linha.

andyp
fonte
Vai na direção certa, obrigado. Consegui inserir o Grid, mas agora preciso dizer ao TabControl que ele deve usar todo o tamanho que ainda está disponível? Como posso conseguir isso?
Citronas
Você precisa adicionar o atributo "Grid.Row" para o TabControl e dar à definição de linha correspondente uma altura de "*" - exatamente como mostrado no exemplo.
andyp
0

Eu tentei muitos métodos aqui, mas não consigo resolver meu problema. (Preencha outro controle no controle)

Até que eu encontrei -lo

<Name_Control Height="auto" Width="auto"/>
//default
//HorizontalAlignment="Stretch" 
//VerticalAlignment="Stretch"

Exemplo:

//UserControl:
<UserControl Name="UC_Test" Height="auto" Width="auto" />
//Grid: 
<Grid Name="Grid_test" Grid.ColumnSpan="2" Grid.Row="2" />
//Code: 
Grid_test.Children.Add(UC_Test);

Para design fácil

<UserControl Name="UC_Test" Height="100" Width="100" />
//Code
Grid_test.Children.Add(UC_Test);
UC_Test.Width = Double.NaN;
UC_Test.Height = Double.NaN;
Trương Quốc Khánh
fonte