Wie bekomme ich Steuerelemente in WPF, um verfügbaren Speicherplatz zu füllen?

304

Einige WPF-Steuerelemente (wie das Button) scheinen den gesamten verfügbaren Speicherplatz in ihrem Container zu belegen, wenn Sie nicht die Höhe angeben, die sie haben sollen.

Und einige, wie die, die ich jetzt verwenden muss, die (mehrzeilige) TextBoxund die ListBoxscheinen mehr besorgt darüber zu sein, nur den Platz zu nehmen, der für ihren Inhalt erforderlich ist, und nicht mehr.

Wenn Sie diese Typen in eine Zelle in einer Zelle stecken UniformGrid, werden sie erweitert, um dem verfügbaren Platz zu entsprechen. Allerdings UniformGridgibt Fälle , für alle Situationen nicht richtig. Was ist, wenn Sie ein Raster mit einigen Zeilen haben, die auf eine * Höhe eingestellt sind, um die Höhe zwischen sich selbst und anderen * Zeilen zu teilen? Was ist, wenn Sie ein StackPanelund ein Label, ein Listund ein haben Button, wie können Sie die Liste dazu bringen, den gesamten Platz einzunehmen, der nicht vom Etikett und der Schaltfläche belegt wird?

Ich würde denken, dass dies wirklich eine grundlegende Layoutanforderung wäre, aber ich kann nicht herausfinden, wie ich sie dazu bringen kann, den Raum zu füllen, den sie könnten ( DockPaneles scheint auch nicht zu funktionieren, sie in eine zu setzen und sie so zu setzen, dass sie gefüllt werden, da das DockPanelnimmt nur den Platz ein, den seine Untersteuerungen benötigen).

Eine veränderbare GUI wäre ganz schrecklich , wenn Sie mit spielen haben Height, Width, MinHeight, MinWidthusw.

Können Sie Ihre Heightund WidthEigenschaften an die von Ihnen belegte Gitterzelle binden? Oder gibt es einen anderen Weg, dies zu tun?

Rune Jacobsen
quelle
1
UniformGrid ist unglaublich, mein neues Standard-Goto-Tag. Ich mochte die Einfachheit der Stackpanels (erinnert mich an ein Div), aber Uniform Grid macht genau das, was ich brauche.
Terrance
Re UniformGrid. Der Schwerpunkt liegt auf Uniform. Scheint, dass Sie die Spaltenbreiten keine Zeilenhöhen anpassen können. Es ist nur geeignet, wenn jeder Inhalt die gleiche Größe hat. Ich habe mein StackPanel durch ein Grid ersetzt, und Stretch hat dann so funktioniert, wie ich es erwartet hatte.
pdschuller
Dieser Artikel hat mir geholfen, Textfelder zu dehnen.
Jpaugh

Antworten:

162

Jedes Steuerelement, das von abgeleitet wird, Panelimplementiert eine unterschiedliche Layoutlogik, die in Measure()und ausgeführt wird Arrange():

  • Measure() bestimmt die Größe des Panels und jedes seiner untergeordneten Elemente
  • Arrange() bestimmt das Rechteck, in dem jedes Steuerelement gerendert wird

Das letzte Kind des DockPanelfüllt den verbleibenden Raum aus. Sie können dieses Verhalten deaktivieren, indem Sie die LastChildEigenschaft auf festlegen false.

Der StackPanelfragt jedes Kind nach seiner gewünschten Größe und stapelt sie dann. Das Stapelfenster ruft Measure()jedes untergeordnete Element mit einer verfügbaren Größe von auf Infinityund verwendet dann die gewünschte Größe des untergeordneten Elements.

A Gridbelegt den gesamten verfügbaren Platz, stellt jedoch jedes Kind auf die gewünschte Größe ein und zentriert es dann in der Zelle.

Sie können Ihre eigene Layoutlogik durch Ableiten von implementieren Panelund dann überschrieben MeasureOverride()und ArrangeOverride().

In diesem Artikel finden Sie ein einfaches Beispiel.

user3837
quelle
8
Link ist jetzt tot
user3690202
6
@ user3690202 Archive.org ist dein Freund. Link wiederbelebt.
Ruffin
4
Das Thema existiert noch in MSDN, aber der Link wurde in diesen geändert: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/…
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: Dies war der fehlende Schlüssel zu meinem Verständnis. Ich dachte immer, dass das Element ohne explizites Dock den Raum füllte.
Spotted
238

Es gibt auch einige Eigenschaften, die Sie festlegen können, um ein Steuerelement zu zwingen, seinen verfügbaren Speicherplatz zu füllen, wenn dies sonst nicht der Fall wäre. Zum Beispiel können Sie sagen:

HorizontalContentAlignment="Stretch"

... um den Inhalt eines Steuerelements horizontal zu dehnen. Oder Sie können sagen:

HorizontalAlignment="Stretch"

... um das Steuerelement selbst zu zwingen, sich horizontal zu strecken, um das übergeordnete Element zu füllen.

Matt Hamilton
quelle
88
Das berüchtigtste Panel, das in all diesen Fällen erwähnt wird, ist das StackPanel. Es enthält keine ContentAlignment-Eigenschaften, und das Festlegen der untergeordneten Elemente auf "Strecken" hat innerhalb eines sterngroßen Rasters keine Auswirkungen. Sehr frustrierend. Es ist fast so, als wäre das StackPanel der erste Container, den das WPF-Team geschrieben hat, und es leidet darunter.
Brent Schooley
4
@Brent - ahh! Ich habe versucht, den Inhalt meines Stackpanels korrekt zu füllen. Vielen Dank! Ich dachte, es sei nur etwas, was ich sehr falsch gemacht habe.
Ashley Grenon
8
@townsean Stack Panel ist sehr begrenzt, Sie können ein ähnliches Verhalten beim Strecken mit einem UniformGrid und Setzen von Zeilen oder Spalten auf 0
ForbesLindesay
2
@ Tuskan360 UniformGrid erlaubt nur, dass die Zellen dieselbe Größe haben. Ich habe am Ende ein Grid benutzt, scheint zu funktionieren. Ärgerlich, dass StackPanel nicht das tut, wofür es anscheinend entwickelt wurde.
TarkaDaal
4
@TarkaDaal yeh, UniformGrid, wenn alles die gleiche Größe hat, Grid, wenn Sie komplexe relative Größen angeben möchten, das Panel auf die Größe basierend auf dem Inhalt stapeln und ignorieren, wie viel Speicherplatz verfügbar ist.
ForbesLindesay
18

Nun, ich habe es gleich nach dem Posten selbst herausgefunden, was der peinlichste Weg ist. :) :)

Es scheint, dass jedes Mitglied eines StackPanels einfach seine gewünschte Mindestgröße ausfüllt.

Im DockPanel hatte ich die Dinge in der falschen Reihenfolge angedockt. Wenn die TextBox oder ListBox das einzige angedockte Element ohne Ausrichtung ist oder wenn sie zuletzt hinzugefügt wurden, füllen sie den verbleibenden Platz wie gewünscht aus.

Ich würde gerne eine elegantere Methode sehen, um damit umzugehen, aber es wird reichen.

Rune Jacobsen
quelle
Ich möchte nur darauf hinweisen (zu dieser alten Frage!), Dass "ohne Ausrichtung" hier ein Schlüsselbegriff ist, zumindest für mich.
MikeBaz - MSFT
4

Verwenden Sie die Layouteigenschaften HorizontalAlignment und VerticalAlignment . Sie steuern, wie ein Element den Platz in seinem übergeordneten Element nutzt, wenn mehr Platz verfügbar ist, als für das Element erforderlich ist.

Die Breite eines StackPanels ist beispielsweise so breit wie das breiteste Element, das es enthält. Alle schmaleren Elemente haben also etwas mehr Platz. Die Ausrichtungseigenschaften steuern, was das untergeordnete Element mit dem zusätzlichen Speicherplatz tut.

Der Standardwert für beide Eigenschaften ist "Strecken", sodass das untergeordnete Element gestreckt wird, um den gesamten verfügbaren Speicherplatz auszufüllen. Zusätzliche Optionen sind Links, Mitte und Rechts für die horizontale Ausrichtung sowie Oben, Mitte und Unten für die vertikale Ausrichtung .

Urini
quelle
31
Wenn dies immer wahr wäre, wäre die ursprüngliche Frage nicht gestellt worden. Nehmen Sie zum Beispiel ein horizontales StackPanel mit einem Label und einer TextBox. Rechts neben der TextBox ist zusätzlicher Platz. Das Textfeld ist auf Automatische Breite eingestellt. Wenn Sie Stretch für HorizontalAlignment festlegen, füllt das Textfeld den verbleibenden Platz nicht aus.
Brent Schooley
Nichts ist immer wahr, aber diese Antwort funktioniert für meine Bedürfnisse: DockPanel, Image.
Alehro