Comment utiliser DockStyle.Fill pour les contrôles standard dans WPF?

92

Je suis habitué à partir des formulaires Windows, que je crée un panneau, place des contrôles à l'intérieur et leur donne la DockStyle.Filltaille maximale du panneau environnant.

Dans WPF, je veux avoir la même chose. J'ai un TabControl et je veux que sa taille remplisse le plus possible le formulaire. J'ai un contrôle de ruban (RibbonControlsLibrary) et je veux que le reste du formulaire soit rempli avec le TabControl à la taille maximale.

(Je ne veux pas ancrer des contrôles comme l'ancrage dans Visual Studio, juste d'anciens mécanismes d'ancrage)

citronas
la source

Réponses:

181

L'équivalent WPF de DockStyle.Fill de WinForms est:

HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Il s'agit de la valeur par défaut pour presque les contrôles, donc en général, vous n'avez rien à faire pour qu'un contrôle WPF remplisse son conteneur parent : ils le font automatiquement. Cela est vrai pour tous les conteneurs qui ne pressent pas leurs enfants à la taille minimale.

Erreurs fréquentes

Je vais maintenant vous expliquer plusieurs erreurs courantes qui empêchent HorizontalAlignment="Stretch" VerticalAlignment="Stretch"de fonctionner comme prévu.

1. Hauteur ou largeur explicites

Une erreur courante consiste à spécifier explicitement une largeur ou une hauteur pour un contrôle. Donc, si vous avez ceci:

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

Supprimez simplement les attributs Largeur et Hauteur:

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

2. Le panneau contenant le contrôle à la taille minimale

Une autre erreur courante est d'avoir le panneau contenant serrant votre contrôle aussi fort que possible. Par exemple, un StackPanel vertical pressera toujours son contenu verticalement aussi petit que possible:

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

Passez à un autre panneau et vous serez prêt à partir:

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

En outre, toute ligne ou colonne de grille dont la hauteur est «Auto» pressera de la même manière son contenu dans cette direction.

Voici quelques exemples de conteneurs qui ne pressent pas leurs enfants:

  • ContentControls ne presse jamais leurs enfants (cela inclut Border, Button, CheckBox, ScrollViewer et bien d'autres)
  • Grille avec une seule ligne et colonne
  • Grille avec des lignes et des colonnes de taille "*"
  • DockPanel ne serre pas son dernier enfant
  • TabControl ne serre pas son contenu

Voici quelques exemples de conteneurs qui pressent leurs enfants:

  • StackPanel serre dans sa direction d'orientation
  • La grille avec une ligne ou une colonne de taille "Auto" se glisse dans cette direction
  • DockPanel serre tout sauf son dernier enfant dans la direction du dock
  • TabControl serre son en-tête (ce qui est affiché sur l'onglet)

3. Hauteur ou largeur explicite plus loin

C'est incroyable le nombre de fois où je vois Grid ou DockPanel avec une hauteur et une largeur explicites, comme ceci:

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

En général, vous ne voulez jamais donner à un panneau une hauteur ou une largeur explicite. Ma première étape lors du diagnostic des problèmes de mise en page est de supprimer toutes les hauteurs ou largeurs explicites que je peux trouver.

4. La fenêtre est SizeToContent alors qu'elle ne devrait pas l'être

Lorsque vous utilisez SizeToContent, votre contenu sera réduit à la taille minimale. Dans de nombreuses applications, c'est très utile et c'est le bon choix. Mais si votre contenu n'a pas de taille "naturelle", vous voudrez probablement omettre SizeToContent.

Ray Burns
la source
J'ai laissé ici une nouvelle question assez complexe liée à la mise en page . Après avoir lu votre réponse, je pense que vous pouvez la comprendre. Cheers
Berryl
7
Excellente réponse! J'aimerais pouvoir en quelque sorte vous donner des points bonus. :)
Jim Raden
@Jim Raden: Vous pouvez ajouter une prime à cette question et attribuer les points à Ray Burns;)
citronas
1
Note d'accompagnement aux futurs lecteurs: il ne sera pas mis à jour dans la vue de conception tant que vous ne serez pas recompilé.
David
"<Button Content =" Pourquoi est-ce que je ne remplis pas la fenêtre? "Width =" 200 "Height =" 20 "/>" m'a fait craquer! XD
Jack Frost
7

Vous pouvez faire ce que vous voulez en disant simplement DockPanel LastChildFill="True"et en vous assurant que ce que vous voulez être le remplisseur est en fait le dernier enfant!

La grille est la bête d'une mise en page que vous pouvez faire presque tout, mais le DockPanel est généralement le bon choix pour votre panneau de mise en page le plus externe. Voici un exemple de psuedocode:

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

    <MyFillingTabControl />
</DockPanel>
Berryl
la source
5

enveloppez simplement vos contrôles dans une grille avec deux lignes. La grille utilisera automatiquement tout l'espace qui lui est donné et vous pouvez définir les lignes pour occuper tout l'espace restant en leur donnant une hauteur de "*". La première ligne de mon exemple (Height = "Auto") prendra autant d'espace que nécessaire par le ruban. J'espère que cela pourra aider.

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

  <Ribbon Grid.Row="0" />

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

En ajoutant l'attribut "Grid.Row = .." aux contrôles enfants de la grille, ils sont affectés aux lignes de la grille. Ensuite, la grille dimensionnera ses enfants comme défini par les définitions de ligne.

Andyp
la source
Va dans la bonne direction, merci. J'ai réussi à insérer la grille, mais maintenant je dois dire au TabControl qu'il doit utiliser toute la taille qui est encore disponible? Comment puis-je y parvenir?
citronas
Vous devez ajouter l'attribut "Grid.Row" pour le TabControl et donner à la définition de ligne correspondante une hauteur de "*" - comme indiqué dans l'exemple.
andyp
0

J'ai essayé plusieurs méthodes ici mais je ne peux pas résoudre mon problème. (Remplissez l'autre contrôle dans le contrôle)

Jusqu'à ce que je l' ai trouvé il

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

Exemple:

//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);

Pour une conception simple

<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
la source