Lekcja 5. Layouty i panele — Grid, StackPanel, WrapPanel, DockPanel
ŚredniPo co się tego uczymy?
Samo dodanie kilku przycisków do okna to za mało — użytkownik musi się w interfejsie łatwo odnaleźć, a okno powinno wyglądać dobrze niezależnie od tego, jak je rozciągniemy. Do tego służą layouty (układy) — specjalne kontenery, które automatycznie rozmieszczają inne elementy, zamiast ręcznie ustawiać każdy piksel.
Teoria
Można powiedzieć, że layout to sposób ułożenia mebli w pokoju, a poszczególne kontrolki (przyciski, pola tekstowe) to te meble. Zamiast przesuwać każdy element ręcznie i liczyć piksele, mówimy panelowi "ułóż wszystko pionowo" albo "podziel okno na dwie kolumny", a on robi to automatycznie — również wtedy, gdy użytkownik zmieni rozmiar okna.
Najważniejsze panele układu w WPF:
- Grid — dzieli okno na wiersze i kolumny (jak arkusz kalkulacyjny albo tabela HTML). To najczęściej używany panel, idealny do formularzy;
- StackPanel — ustawia elementy jeden za drugim, w pionie (domyślnie) lub w poziomie (
Orientation="Horizontal"). Świetny do prostych list i grup przycisków; - WrapPanel — ustawia elementy obok siebie i automatycznie "zawija" je w nowy rząd, gdy zabraknie miejsca — jak tekst, który się zawija na końcu linii;
- DockPanel — przypina elementy do krawędzi okna: góry, dołu, lewej lub prawej strony. Klasyczne zastosowanie: pasek menu na górze, pasek statusu na dole, treść pośrodku;
- Canvas — pozwala ustawić dokładną pozycję X/Y każdego elementu ręcznie. Rzadko używany do zwykłych formularzy (bo nie dostosowuje się do rozmiaru okna), ale przydatny do rysowania, gier czy diagramów;
- GroupBox — nie jest typowym layoutem, tylko ramką z nagłówkiem, wewnątrz której umieszcza się inny panel — służy do wizualnego grupowania powiązanych pól formularza.
W praktyce panele często się zagnieżdża — np. DockPanel jako główny kontener okna (menu na górze, treść na środku), a wewnątrz treści Grid układający formularz w wiersze i kolumny.
Najważniejsze właściwości paneli
| Właściwość | Opis |
|---|---|
Orientation |
Kierunek elementów w StackPanel: Horizontal lub Vertical. |
Margin |
Odstęp zewnętrzny od innych elementów (góra, prawo, dół, lewo — np. Margin="0,5,0,0"). |
Padding |
Wewnętrzny odstęp od zawartości kontenera. |
DockPanel.Dock |
Przypina element wewnątrz DockPanel do krawędzi: Top, Bottom, Left, Right. |
HorizontalAlignment / VerticalAlignment |
Wyrównanie elementu: Left/Right/Center/Stretch (poziomo), Top/Bottom/Center/Stretch (pionowo). |
Header |
Tytuł wyświetlany w nagłówku GroupBox lub MenuItem. |
Grid.RowDefinitions / Grid.ColumnDefinitions |
Definicja podziału siatki Grid na wiersze/kolumny — szerokości Auto (dopasuj do treści), * (proporcjonalnie, cała reszta) albo konkretna liczba pikseli. |
Grid.Row / Grid.Column |
Ustawiana na dziecku Grid — wskazuje, w której komórce siatki ma się znaleźć element. |
Dla porównania: layouty w Windows Forms
Na egzaminie INF.04 może pojawić się pytanie dotyczące Windows Forms — starszej, lecz wciąż spotykanej technologii desktopowej w C#. W Windows Forms nie ma XAML — układ projektuje się wizualnie, przeciągając kontrolki myszą na formularz w Visual Studio. Rolę layoutów WPF pełnią tam inne kontenery:
| WPF | Odpowiednik w Windows Forms | Działanie |
|---|---|---|
StackPanel |
FlowLayoutPanel |
Ustawia elementy jeden po drugim, w rzędzie lub kolumnie. |
Grid |
TableLayoutPanel |
Dzieli przestrzeń na wiersze i kolumny. |
DockPanel |
właściwość Dock kontrolki + MenuStrip/ToolStrip |
Przypina elementy do krawędzi formularza. |
GroupBox |
GroupBox |
Ramka z tytułem — ta sama nazwa w obu technologiach. |
| — | SplitContainer |
Dzieli okno na dwie części z ruchomym uchwytem (w WPF podobny efekt daje GridSplitter). |
Kluczowa różnica: WPF automatycznie dopasowuje układ do rozmiaru okna dzięki deklaratywnemu, elastycznemu XAML, natomiast Windows Forms opiera się bardziej na współrzędnych i właściwości Anchor (przyklejenie krawędzi kontrolki do krawędzi formularza przy zmianie rozmiaru) — układ jest z natury bardziej statyczny i wymaga więcej ręcznej pracy przy dostosowywaniu do różnych rozdzielczości.
Schemat
Najwazniejsze panele ukladu w WPF:
Grid (wiersze x kolumny) StackPanel (jeden rzad/kolumna)
┌─────────┬─────────┐ ┌─────────────────┐
│ [0,0] │ [0,1] │ │ Element 1 │
├─────────┼─────────┤ ├─────────────────┤
│ [1,0] │ [1,1] │ │ Element 2 │
└─────────┴─────────┘ ├─────────────────┤
│ Element 3 │
└─────────────────┘
WrapPanel (zawija w nowy rzad) DockPanel (przypina do krawedzi)
┌───┬───┬───┐ ┌───────Top────────┐
│ A │ B │ C │ │Left│ srodek │Right│
├───┼───┘ │ │ │ │
│ D │ <- zawiniete ├────┴─────────┴─────┤
└───┘ │ Bottom │
└─────────────────────┘
Przykład z życia
Otwórz dowolny program biurowy — pasek menu zawsze jest przypięty do góry okna (to DockPanel), przyciski w oknie dialogowym "Zapisz jako" są ułożone w rzędzie na dole (to StackPanel poziomy), a formularz z danymi osobowymi ma etykiety i pola ułożone w równe kolumny (to Grid) — nawet jeśli okno zostanie rozciągnięte na cały ekran, układ pozostaje czytelny, bo panele same przeliczają rozmieszczenie.
Kod (XAML)
<Window x:Class="UkladyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Formularz uzytkownika" Height="300" Width="400">
<DockPanel>
<!-- Pasek menu przypiety do gory -->
<Menu DockPanel.Dock="Top">
<MenuItem Header="_Plik">
<MenuItem Header="Nowy" />
<MenuItem Header="Zapisz" />
<Separator />
<MenuItem Header="Zamknij" />
</MenuItem>
</Menu>
<!-- Glowna sekcja z formularzem w Grid wewnatrz GroupBox -->
<GroupBox Header="Dane uzytkownika" Margin="10">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Imie:" Grid.Row="0" Grid.Column="0" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" />
<Label Content="Nazwisko:" Grid.Row="1" Grid.Column="0" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="5" />
</Grid>
</GroupBox>
</DockPanel>
</Window>
Komentarz i wyjaśnienie kodu
Główny kontener to DockPanel — Menu ma ustawione DockPanel.Dock="Top", więc zawsze zostanie przypięty do góry okna, niezależnie od jego rozmiaru. Reszta przestrzeni (domyślnie ostatni element w DockPanel wypełnia pozostałe miejsce) należy do GroupBox z formularzem.
Wewnątrz GroupBox mamy Grid z dwoma zdefiniowanymi wierszami (RowDefinitions) i dwiema kolumnami (ColumnDefinitions) — pierwsza kolumna ma szerokość Auto (dopasowuje się do treści etykiety), druga * (zajmuje całą resztę dostępnego miejsca). Każda kontrolka wskazuje, w którym wierszu/kolumnie ma się znaleźć przez Grid.Row i Grid.Column — to jak podanie współrzędnych komórki w tabeli.
Ćwiczenie samodzielne
Utwórz nowy projekt WPF, wklej powyższy XAML i uruchom aplikację. Zmień szerokość okna (przeciągając krawędź) i zaobserwuj, jak menu zawsze zostaje na górze, a pola formularza dopasowują szerokość do dostępnego miejsca.
Zadania do pracy własnej
Zbuduj okno z
StackPanel(poziomym,Orientation="Horizontal") zawierającym trzy przyciski obok siebie: "Dodaj", "Edytuj", "Usuń".Rozbuduj formularz z lekcji o trzecie pole (Email) i dodaj na dole (przypięty przez
DockPanel.Dock="Bottom") pasek z przyciskami "Zapisz" i "Anuluj" ułożonymi poziomo.Zaprojektuj okno symulujące prosty edytor zdjęć: pasek menu na górze (
DockPanel.Dock="Top"), pasek narzędzi z ikonami po lewej (DockPanel.Dock="Left",WrapPanelpionowy), pasek statusu na dole, a na środku duży obszar roboczy (może być zwykłyBorderz szarym tłem, symbolizujący miejsce na obraz).
Typowe błędy
Używanie Canvas jako głównego układu okna — pozycje X/Y ustawione ręcznie NIE dostosowują się do zmiany rozmiaru okna, przez co interfejs "rozjeżdża się" przy innej rozdzielczości ekranu. Canvas ma sens tylko do specyficznych zastosowań (rysowanie, gry).
Zapominanie o RowDefinitions/ColumnDefinitions w Grid — bez jawnego zdefiniowania wierszy/kolumn, Grid ma domyślnie tylko jeden wiersz i jedną kolumnę, więc wszystkie elementy nakładają się na siebie w tym samym miejscu.
Mylenie kolejności elementów w DockPanel — elementy dokują się w kolejności, w jakiej występują w XAML; ostatni element (bez ustawionego Dock) domyślnie wypełnia całą pozostałą przestrzeń.
Nawiązanie do egzaminu zawodowego
To rozwinięcie efektu INF.04.5.3 w części dotyczącej projektowania interfejsu okna. Dobrze dobrany layout to podstawa czytelnej aplikacji — w kolejnej lekcji dodamy do tych paneli prawdziwe, interaktywne kontrolki i nauczymy się obsługiwać zdarzenia.