Comment obtenir des contrôles dans WPF pour remplir l'espace disponible?

304

Certains contrôles WPF (comme le Button) semblent consommer avec bonheur tout l'espace disponible dans son conteneur si vous ne spécifiez pas la hauteur qu'il doit avoir.

Et certains, comme ceux que je dois utiliser en ce moment, les (multilignes) TextBoxet les ListBoxsemblent plus inquiets de ne prendre que l'espace nécessaire pour adapter leur contenu, et pas plus.

Si vous mettez ces gars dans une cellule dans un UniformGrid, ils se développeront pour s'adapter à l'espace disponible. Cependant, les UniformGridinstances ne conviennent pas à toutes les situations. Que se passe-t-il si vous avez une grille avec certaines lignes définies sur une * hauteur pour diviser la hauteur entre elle-même et les autres * lignes? Et si vous avez un StackPanelet vous avez un Label, un Listet un Button, comment pouvez-vous faire en sorte que la liste occupe tout l'espace non consommé par l'étiquette et le bouton?

Je pense que ce serait vraiment une exigence de mise en page de base, mais je ne sais pas comment les faire remplir l'espace qu'ils pourraient (les mettre dans un DockPanelet le configurer pour remplir ne fonctionne pas non plus, semble-t-il, car la DockPanelseule occupe l'espace nécessaire à ses «sous-commandes».

Une interface graphique redimensionnable serait vraiment horrible si vous deviez jouer avec Height, Width, MinHeight, MinWidthetc.

Pouvez-vous lier vos propriétés Heightet Widthà la cellule de grille que vous occupez? ou y a-t-il une autre manière de le faire?

Rune Jacobsen
la source
1
UniformGrid est incroyable, ma nouvelle balise goto par défaut. J'ai aimé la simplicité des Stackpanels (ça me rappelle une div) mais Uniform Grid fait exactement ce dont j'ai besoin.
Terrance
Re UniformGrid. L'accent est mis sur l'uniforme. Il semble que vous ne puissiez pas ajuster la largeur des colonnes ni la hauteur des lignes. Il ne convient que si chaque élément de contenu est de la même taille. J'ai remplacé mon StackPanel par une grille, et Stretch a ensuite fonctionné comme je m'y attendais.
pdschuller
Cet article m'a aidé à étirer les zones de texte.
jpaugh

Réponses:

162

Chaque contrôle dérivant de Panelimplémente une logique de mise en page distincte effectuée dans Measure()et Arrange():

  • Measure() détermine la taille du panneau et de chacun de ses enfants
  • Arrange() détermine le rectangle dans lequel chaque contrôle s'affiche

Le dernier enfant du DockPanelremplit l'espace restant. Vous pouvez désactiver ce comportement en définissant la LastChildpropriété sur false.

Le StackPaneldemande à chaque enfant la taille souhaitée, puis les empile. Le panneau de pile fait appel Measure()à chaque enfant, avec une taille disponible de Infinitypuis utilise la taille souhaitée de l'enfant.

A Gridoccupe tout l'espace disponible, cependant, il mettra chaque enfant à la taille souhaitée, puis les centrera dans la cellule.

Vous pouvez implémenter votre propre logique de mise en page en dérivant Panelpuis en remplaçant MeasureOverride()et ArrangeOverride().

Voir cet article pour un exemple simple.

user3837
la source
8
Link is now dead
user3690202
6
@ user3690202 Archive.org est votre ami. Lien réanimé.
ruffin
4
Le sujet existe toujours dans MSDN, mais le lien a changé comme suit
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: c'était la clé manquante à ma compréhension. J'ai toujours pensé que l'élément sans Dock explicite remplissait l'espace.
Repéré le
238

Il existe également certaines propriétés que vous pouvez définir pour forcer un contrôle à remplir son espace disponible alors qu'il ne le ferait pas autrement. Par exemple, vous pouvez dire:

HorizontalContentAlignment="Stretch"

... pour forcer le contenu d'un contrôle à s'étirer horizontalement. Ou vous pouvez dire:

HorizontalAlignment="Stretch"

... pour forcer le contrôle lui-même à s'étirer horizontalement pour remplir son parent.

Matt Hamilton
la source
88
Le panneau le plus notoire mentionné dans tous ces cas est le StackPanel. Il ne contient pas de propriétés ContentAlignment et la définition de ses enfants sur Stretch n'aura aucun effet à l'intérieur d'une grille de taille étoile. Très frustrant. C'est presque comme si le StackPanel était le premier conteneur écrit par l'équipe WPF et cela en souffre.
Brent Schooley le
4
@Brent - ahh! J'ai été coincé à essayer de remplir correctement le contenu de mon stackpanel. Merci! Je pensais que c'était juste quelque chose que je faisais très mal.
Ashley Grenon
8
Le panneau @townsean Stack est très limité, vous pouvez obtenir un comportement similaire en étirant à l'aide d'un UniformGrid et en définissant des lignes ou des colonnes sur 0
ForbesLindesay
2
@ Tuskan360 UniformGrid permet uniquement aux cellules d'avoir la même taille. J'ai utilisé une grille à la fin, semble fonctionner. Ennuyeux de voir comment StackPanel ne fait pas ce pour quoi il est apparemment conçu.
TarkaDaal
4
@TarkaDaal yeh, UniformGrid si tout est de la même taille, Grid si vous voulez spécifier des tailles relatives complexes, empilez le panneau à la taille juste basée sur le contenu et ignorez l'espace disponible.
ForbesLindesay
18

Eh bien, je l'ai compris moi-même, juste après la publication, ce qui est le moyen le plus embarrassant. :)

Il semble que chaque membre d'un StackPanel remplira simplement sa taille minimale requise.

Dans le DockPanel, j'avais ancré les choses dans le mauvais ordre. Si le TextBox ou ListBox est le seul élément ancré sans alignement, ou s'ils sont les derniers ajoutés, ils rempliront l'espace restant comme souhaité.

J'adorerais voir une méthode plus élégante pour gérer cela, mais cela fera l'affaire.

Rune Jacobsen
la source
Je veux juste souligner (sur cette vieille question!) Que "sans alignement" est une phrase clé ici, du moins c'était pour moi.
MikeBaz - MSFT
4

Utilisez les propriétés de disposition HorizontalAlignment et VerticalAlignment . Ils contrôlent la façon dont un élément utilise l'espace qu'il a à l'intérieur de son parent lorsqu'il y a plus d'espace disponible qu'il n'en a besoin par l'élément.

La largeur d'un StackPanel, par exemple, sera aussi large que l'élément le plus large qu'il contient. Ainsi, tous les éléments plus étroits ont un peu d'espace excédentaire. Les propriétés d'alignement contrôlent ce que l'élément enfant fait avec l'espace supplémentaire.

La valeur par défaut pour les deux propriétés est Stretch, donc l'élément enfant est étiré pour remplir tout l'espace disponible. Les options supplémentaires incluent Gauche, Centre et Droite pour l' alignement horizontal et Haut, Centre et Bas pour l' alignement vertical .

urini
la source
31
Si cela était toujours vrai, la question initiale n'aurait pas été posée. Prenez, par exemple, un StackPanel horizontal avec un Label et un TextBox. Il y a de l'espace supplémentaire à droite de la TextBox. La TextBox est définie sur Largeur automatique. La définition de Stretch pour HorizontalAlignment ne fera pas le TextBox remplir l'espace restant.
Brent Schooley
Rien n'est toujours vrai mais cette réponse fonctionne pour mes besoins: DockPanel, Image.
alehro