Jak uzyskać kontrole w WPF, aby wypełnić dostępne miejsce?

303

Niektóre elementy sterujące WPF (takie jak Button) wydają się szczęśliwie zajmować całą dostępną przestrzeń w swoim kontenerze, jeśli nie określisz wysokości, jaką ma mieć.

I niektórzy, jak ci, których muszę teraz używać, (wielowierszowy) TextBoxi ListBoxwydają się bardziej zaniepokojeni po prostu zajmowaniem miejsca niezbędnego do dopasowania ich zawartości i więcej.

Jeśli umieścisz tych facetów w komórce w UniformGrid, rozwiną się, aby dopasować się do dostępnej przestrzeni. Jednak UniformGridinstancje nie są odpowiednie dla wszystkich sytuacji. Co zrobić, jeśli masz siatkę z niektórymi rzędami ustawionymi na * wysokość, aby podzielić wysokość między siebie i inne * rzędy? Co jeśli masz a StackPaneli a Label, Lista Button, jak możesz sprawić, by lista zajmowała całe miejsce, które nie zostało zjedzone przez etykietę i przycisk?

Myślę, że to naprawdę byłby podstawowy wymóg dotyczący układu, ale nie mogę wymyślić, jak zmusić je do wypełnienia przestrzeni, którą mogłyby (włożenie DockPaneli ustawienie wypełnienia również nie działa, wydaje się, ponieważ DockPanelzajmuje tylko przestrzeń potrzebną jej subcontrols).

Resizable GUI byłoby dość straszne, jeśli trzeba było grać Height, Width, MinHeight, MinWidthitd.

Czy możesz powiązać swoje Heighti Widthwłaściwości z zajmowaną komórką siatki? Czy jest na to inny sposób?

Rune Jacobsen
źródło
1
UniformGrid jest niesamowity, Mój nowy domyślny tag goto. Podobała mi się prostota Stackpanels (przypomina mi div), ale Uniform Grid robi dokładnie to, czego potrzebuję.
Terrance
Re UniformGrid. Nacisk kładziony jest na Uniform. Wydaje się, że nie można dopasować szerokości kolumn i wysokości wierszy. Jest odpowiedni tylko wtedy, gdy każdy element treści ma ten sam rozmiar. Zastąpiłem mój StackPanel siatką, a następnie Stretch działał zgodnie z oczekiwaniami.
pdschuller
Ten artykuł pomógł mi rozciągnąć pola tekstowe.
jpaugh

Odpowiedzi:

162

Każda kontrola pochodzące z Panelnarzędzi odrębny układ logiczny wykonanych w Measure()i Arrange():

  • Measure() określa rozmiar panelu i każdego z jego dzieci
  • Arrange() określa prostokąt, w którym renderowany jest każdy formant

Ostatnie dziecko DockPanelwypełnia pozostałą przestrzeń. Możesz wyłączyć to zachowanie, ustawiając LastChildwłaściwość na false.

StackPanelProsi każdego dziecka do jego żądanej wielkości, a następnie układa je. Panel stosu wywołuje Measure()każde dziecko, z dostępnym rozmiarem, Infinitya następnie używa pożądanego rozmiaru dziecka.

A Gridzajmuje całą dostępną przestrzeń, jednak ustawi każde dziecko do pożądanego rozmiaru, a następnie wyśrodkuje je w komórce.

Możesz zaimplementować własną logikę układu na podstawie, Panela następnie przesłonięcia MeasureOverride()i ArrangeOverride().

Zobacz ten artykuł jako prosty przykład.

użytkownik3837
źródło
8
Link nie działa
3690202
6
@ user3690202 Archive.org jest twoim przyjacielem. Link ożywił się.
ruffin
4
Temat nadal istnieje w MSDN, ale link zmienił się na ten: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/...
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: to był brakujący klucz do mojego zrozumienia. Zawsze uważałem, że element bez wyraźnego Docka wypełniał przestrzeń.
Zauważył
238

Istnieją również pewne właściwości, które można ustawić w celu wymuszenia zapełnienia dostępnej przestrzeni formantu, gdy inaczej by tego nie zrobił. Na przykład możesz powiedzieć:

HorizontalContentAlignment="Stretch"

... aby wymusić rozciągnięcie zawartości kontrolki w poziomie. Lub możesz powiedzieć:

HorizontalAlignment="Stretch"

... aby zmusić samą kontrolkę do rozciągnięcia się w poziomie, aby wypełnić jej element nadrzędny.

Matt Hamilton
źródło
88
Najbardziej znanym panelem wspomnianym we wszystkich tych przypadkach jest StackPanel. Nie zawiera właściwości ContentAlignment, a ustawienie jego elementów potomnych na Rozciągnięcie nie będzie miało wpływu na siatkę wielkości gwiazdy. Bardzo frustrujące. To prawie tak, jakby StackPanel był pierwszym kontenerem napisanym przez zespół WPF i tak właśnie jest.
Brent Schooley
4
@Brent - ahh! Utknąłem na próbie poprawnego wypełnienia zawartości mojego stosu. dzięki! Myślałem, że robię to bardzo źle.
Ashley Grenon,
8
Panel stosu @townsean jest bardzo ograniczony, podobne zachowanie można uzyskać przy rozciąganiu za pomocą UniformGrid i ustawieniu wierszy lub kolumn na 0
ForbesLindesay
2
@ Tuskan360 UniformGrid zezwala tylko na komórki o tym samym rozmiarze. W końcu użyłem siatki, wydaje się, że działa. Irytujące, jak StackPanel nie robi tego, na co wygląda.
TarkaDaal
4
@TarkaDaal yeh, UniformGrid, jeśli wszystko ma ten sam rozmiar, Grid, jeśli chcesz określić złożone względne rozmiary, stos stosu do rozmiaru na podstawie zawartości i zignoruj ​​ilość dostępnego miejsca.
ForbesLindesay
18

Cóż, sam to wymyśliłem, zaraz po opublikowaniu, co jest najbardziej zawstydzającym sposobem. :)

Wygląda na to, że każdy członek StackPanel po prostu wypełni swój minimalny wymagany rozmiar.

W DockPanel zadokowałem rzeczy w niewłaściwej kolejności. Jeśli TextBox lub ListBox jest jedynym zadokowanym elementem bez wyrównania lub jeśli są ostatnim dodanym, wypełnią pozostałe miejsce zgodnie z potrzebami.

Chciałbym zobaczyć bardziej elegancką metodę radzenia sobie z tym, ale tak się stanie.

Rune Jacobsen
źródło
Chcę tylko zwrócić uwagę (na to stare pytanie!), Że „bez wyrównania” jest tutaj kluczowym zwrotem, przynajmniej dla mnie.
MikeBaz - MSFT
4

Użyj właściwości układu HorizontalAlignment i VerticalAlignment . Kontrolują sposób, w jaki element wykorzystuje przestrzeń, którą ma w swoim obiekcie nadrzędnym, gdy dostępne jest więcej miejsca niż wymaga tego element.

Na przykład szerokość StackPanel będzie tak szeroka, jak najszerszy element, jaki zawiera. Tak więc wszystkie węższe elementy mają trochę nadmiaru miejsca. Właściwości wyrównania kontrolują to, co element podrzędny robi z dodatkową przestrzenią.

Domyślną wartością dla obu właściwości jest Rozciągnij, więc element potomny jest rozciągany, aby wypełnić całą dostępną przestrzeń. Dodatkowe opcje obejmują lewy, środkowy i prawy dla wyrównania poziomego oraz górny, środkowy i dolny dla wyrównania pionowego .

urini
źródło
31
Gdyby tak było zawsze, pierwotne pytanie nie zostałoby zadane. Weźmy na przykład poziomy StackPanel z etykietą i TextBox. Po prawej stronie TextBox jest dodatkowe miejsce. TextBox jest ustawiony na Auto width. Ustawienie Rozciągnięcia dla wyrównania poziomego nie spowoduje, że TextBox wypełni pozostałe miejsce.
Brent Schooley
Nic nie jest zawsze prawdziwe, ale ta odpowiedź działa na moje potrzeby: DockPanel, Image.
alehro