StackPanel – układ liniow
Poznasz StackPanel – layout, który układa elementy jeden za drugim, pionowo lub poziomo. Prosty, szybki i idealny do list przycisków, pasków narzędzi i formularzy.
Czym jest StackPanel?
StackPanel to layout, który układa swoje elementy jeden za drugim – jak stos kart albo kolejka. Możesz ustawić kierunek: pionowy (jeden pod drugim) lub poziomy (jeden obok drugiego).
Wyobraź sobie, że wkładasz książki na półkę. Możesz ustawiać je pionowo – jedną na drugiej (jak wieża) lub poziomo – jedną obok drugiej (jak normalnie w bibliotece). StackPanel działa dokładnie tak. Każdy nowy element trafia na koniec kolejki.
StackPanel jest prostszy niż Grid – nie musisz definiować wierszy ani kolumn. Elementy po prostu stoją po sobie. Płacisz za to pewną cenę: mniej kontroli nad rozmieszczeniem.
Orientation – kierunek układania
Vertical – jeden pod drugim (domyślny)
Domyślnie StackPanel układa elementy od góry do dołu.
Nie musisz nawet pisać Orientation="Vertical" – tak jest domyślnie.
<!-- Orientation="Vertical" jest domyślne – można pominąć --> <StackPanel Orientation="Vertical"> <Button Content="Pierwszy" Margin="5" /> <Button Content="Drugi" Margin="5" /> <Button Content="Trzeci" Margin="5" /> </StackPanel> <!-- Wynik: trzy przyciski jeden pod drugim -->
W trybie Vertical każdy element rozciąga się
na całą szerokość StackPanel (HorizontalAlignment = Stretch domyślnie).
Dlatego przyciski są tak szerokie jak cały panel.
Możesz to zmienić ustawiając HorizontalAlignment="Left"
lub podając konkretną szerokość Width="100".
Horizontal – jeden obok drugiego
Po ustawieniu Orientation="Horizontal" elementy układają się
od lewej do prawej.
<StackPanel Orientation="Horizontal"> <Button Content="Cofnij" Margin="5" /> <Button Content="Dalej" Margin="5" /> <Button Content="Anuluj" Margin="5" /> <Button Content="Zapisz" Margin="5" /> </StackPanel> <!-- Wynik: cztery przyciski obok siebie -->
W trybie Horizontal każdy element rozciąga się
na całą wysokość StackPanel (VerticalAlignment = Stretch domyślnie).
Jeśli nie chcesz tego efektu, ustaw konkretną wysokość lub
VerticalAlignment="Center" na elementach.
Odstępy między elementami
Domyślnie elementy w StackPanel stoją ciasno obok siebie – bez żadnych odstępów. Są dwa sposoby, żeby to poprawić.
Margin na elementach-dzieciach
Najczęstszy sposób – każdemu elementowi dajesz Margin.
Pamiętaj, że Margin dodaje przestrzeń z każdej strony, więc między
dwoma elementami z Margin="5" będzie 10px odstępu
(5px górnego + 5px dolnego).
<!-- Każdy element ma 5px marginesu ze wszystkich stron --> <StackPanel> <Button Content="Nowy" Margin="5" /> <Button Content="Otwórz" Margin="5" /> <Button Content="Zapisz" Margin="5" /> </StackPanel> <!-- Margines tylko pionowy – lewa/prawa = 0, góra/dół = 4 --> <StackPanel> <TextBlock Text="Imię:" Margin="0,0,0,4" /> <TextBox Margin="0,0,0,12" /> <TextBlock Text="Nazwisko:" Margin="0,0,0,4" /> <TextBox Margin="0,0,0,12" /> </StackPanel>
Padding na samym StackPanel
Padding dodaje wewnętrzny odstęp między krawędzią
StackPanel a jego zawartością – działa jak margines od wnętrza kontenera.
<!-- 10px odstępu od krawędzi panelu do zawartości --> <StackPanel Padding="10"> <Button Content="Jeden" Margin="0,0,0,5" /> <Button Content="Dwa" Margin="0,0,0,5" /> <Button Content="Trzy" /> </StackPanel>
Padding = przestrzeń od krawędzi panelu do pierwszego elementu.
Margin na dziecku = przestrzeń między tym elementem a sąsiednimi.
Najczęściej używa się albo jednego albo drugiego – stosowanie obu naraz
może dawać nieoczekiwane efekty.
Wyrównanie elementów
Domyślnie dzieci StackPanel rozciągają się na całą dostępną szerokość (w trybie pionowym) lub wysokość (w trybie poziomym). Możesz to zmienić na dwóch poziomach: na całym panelu lub na poszczególnych elementach.
<!-- StackPanel wyrównany do prawej strony okna --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10"> <Button Content="Anuluj" Margin="5,0" Width="80" /> <Button Content="Zapisz" Margin="5,0" Width="80" /> </StackPanel> <!-- Dwa przyciski w prawym dolnym rogu -->
<StackPanel> <!-- Każde dziecko ma inne wyrównanie --> <Button Content="Do lewej" HorizontalAlignment="Left" Width="100" Margin="5" /> <Button Content="Na środku" HorizontalAlignment="Center" Width="100" Margin="5" /> <Button Content="Do prawej" HorizontalAlignment="Right" Width="100" Margin="5" /> <Button Content="Pełna szerokość" HorizontalAlignment="Stretch" Margin="5" /> </StackPanel>
Zagnieżdżanie StackPaneli
StackPanel możesz zagnieżdżać – pionowy wewnątrz poziomego i odwrotnie. To prosty sposób na budowanie złożonych układów bez użycia Grid.
<!-- Zewnętrzny pionowy --> <StackPanel Orientation="Vertical" Margin="10"> <!-- Nagłówek --> <TextBlock Text="Dodaj produkt" FontSize="18" FontWeight="Bold" Margin="0,0,0,10" /> <!-- Wiersz: Etykieta + Pole (poziomy StackPanel) --> <StackPanel Orientation="Horizontal" Margin="0,0,0,8"> <TextBlock Text="Nazwa:" Width="80" VerticalAlignment="Center" /> <TextBox x:Name="txtNazwa" Width="200" /> </StackPanel> <!-- Wiersz: Etykieta + Pole --> <StackPanel Orientation="Horizontal" Margin="0,0,0,8"> <TextBlock Text="Cena:" Width="80" VerticalAlignment="Center" /> <TextBox x:Name="txtCena" Width="200" /> </StackPanel> <!-- Stopka: przyciski w poziomie, do prawej --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0"> <Button Content="Anuluj" Width="80" Margin="0,0,8,0" /> <Button Content="Dodaj" Width="80" /> </StackPanel> </StackPanel>
Zagnieżdżone StackPanele dobrze sprawdzają się przy prostych,
liniowych layoutach. Gdy potrzebujesz, żeby pole tekstowe
zajmowało resztę dostępnej przestrzeni (*), a etykieta była
tylko tak szeroka jak jej tekst – sięgnij po Grid z
Width="Auto" i Width="*".
Zagnieżdżone StackPanele mają stałe szerokości, co bywa ograniczające.
StackPanel w C#
StackPanel możesz tworzyć i modyfikować z kodu C#. Przydaje się gdy chcesz dynamicznie dodawać elementy – np. wczytując dane z listy.
// W XAML: <StackPanel x:Name="panelListy" /> private void Window_Loaded(object sender, RoutedEventArgs e) { string[] produkty = { "Jabłko", "Banan", "Gruszka", "Śliwka" }; foreach (string produkt in produkty) { // Tworzymy wiersz: poziomy StackPanel StackPanel wiersz = new StackPanel(); wiersz.Orientation = Orientation.Horizontal; wiersz.Margin = new Thickness(0, 0, 0, 5); // Etykieta z nazwą produktu TextBlock etykieta = new TextBlock(); etykieta.Text = produkt; etykieta.Width = 120; etykieta.VerticalAlignment = VerticalAlignment.Center; // Przycisk usuń Button btnUsun = new Button(); btnUsun.Content = "Usuń"; btnUsun.Tag = produkt; // zapamiętujemy który produkt btnUsun.Click += BtnUsun_Click; // Składamy wiersz wiersz.Children.Add(etykieta); wiersz.Children.Add(btnUsun); // Dodajemy wiersz do panelu głównego panelListy.Children.Add(wiersz); } } private void BtnUsun_Click(object sender, RoutedEventArgs e) { Button btn = (Button)sender; string nazwa = (string)btn.Tag; MessageBox.Show($"Usuwam: {nazwa}"); }
Tag to specjalna właściwość dostępna na każdej kontrolce WPF.
Możesz tam przechować dowolny obiekt – tekst, liczbę,
referencję. Przydaje się gdy tworzysz kontrolki dynamicznie i chcesz
każdej z nich przypisać dane, do których wrócisz później
(np. w obsłudze zdarzenia Click).
StackPanel vs Grid – kiedy co używać?
| Sytuacja | StackPanel | Grid |
|---|---|---|
| Kilka przycisków obok siebie | ✅ Idealny | ➖ Zbędna złożoność |
| Lista elementów jeden pod drugim | ✅ Idealny | ➖ Da radę, ale więcej kodu |
| Formularz: etykieta + pole tekstowe | ⚠️ Da radę (stałe szerokości) | ✅ Lepszy (Auto + *) |
| Pole ma zajmować „resztę” przestrzeni | ❌ Nie potrafi | ✅ Width="*" |
| Pasek przycisków (toolbar) | ✅ Idealny (Horizontal) | ➖ Można, ale po co |
| Dynamiczne dodawanie elementów | ✅ Bardzo wygodny | ⚠️ Trudniejszy w C# |
| Precyzyjne rozmieszczenie w oknie | ❌ Brak kontroli | ✅ Pełna kontrola |
Używaj StackPanel gdy chcesz szybko ułożyć kilka elementów w linię – pasek przycisków, lista pozycji, prosta nawigacja. Używaj Grid gdy potrzebujesz precyzyjnego rozmieszczenia i kontroli nad rozmiarem – formularze, okna dialogowe, cały layout okna. W prawdziwych aplikacjach oba layouty współpracują: Grid jako szkielet okna, StackPanel do grupowania przycisków i małych elementów.
Praktyczne przykłady
Pasek przycisków akcji
<!-- Pasek z przyciskami: po lewej "Nowy", po prawej "Anuluj/Zapisz" --> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <!-- Przyciski po lewej --> <StackPanel Grid.Column="0" Orientation="Horizontal"> <Button Content="➕ Nowy" Margin="0,0,5,0" Padding="10,5" /> <Button Content="🗑 Usuń" Margin="0,0,5,0" Padding="10,5" /> </StackPanel> <!-- Przyciski po prawej --> <StackPanel Grid.Column="1" Orientation="Horizontal"> <Button Content="Anuluj" Margin="0,0,5,0" Width="70" /> <Button Content="Zapisz" Width="70" /> </StackPanel> </Grid>
Menu boczne (nawigacja)
<!-- Panel boczny z menu nawigacyjnym --> <StackPanel Background="#2d2d3f" Width="180" Padding="0,10"> <TextBlock Text="MENU" Foreground="#888" FontSize="11" Margin="15,0,0,8" /> <Button Content="🏠 Strona główna" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Padding="15,10" Margin="0,1" BorderThickness="0" Background="Transparent" Foreground="White" /> <Button Content="📋 Lista produktów" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Padding="15,10" Margin="0,1" BorderThickness="0" Background="Transparent" Foreground="White" /> <Button Content="⚙️ Ustawienia" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Padding="15,10" Margin="0,1" BorderThickness="0" Background="Transparent" Foreground="White" /> </StackPanel>
Formularz pionowy – prosty
<StackPanel Width="280" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20"> <TextBlock Text="Logowanie" FontSize="22" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20" /> <TextBlock Text="Login" Margin="0,0,0,4" /> <TextBox x:Name="txtLogin" Margin="0,0,0,12" Padding="5" /> <TextBlock Text="Hasło" Margin="0,0,0,4" /> <PasswordBox x:Name="pwdHaslo" Margin="0,0,0,20" Padding="5" /> <Button x:Name="btnZaloguj" Content="Zaloguj się" Padding="0,10" Click="btnZaloguj_Click" /> </StackPanel>
Częste błędy w StackPanel
❌ Błąd 1: StackPanel nie scrolluje sam z siebie
❌ Elementy wychodzą poza ekran
<StackPanel>
<!-- 50 elementów...
te na dole niewidoczne,
brak scrolla -->
</StackPanel>
✅ Owij w ScrollViewer
<ScrollViewer>
<StackPanel>
<!-- 50 elementów –
teraz można scrollować -->
</StackPanel>
</ScrollViewer>
❌ Błąd 2: Zapomniany Orientation
❌ Chciałem poziomo, wychodzi pionowo
<StackPanel>
<!-- Domyślnie Vertical!
Przyciski jeden pod drugim -->
<Button Content="Jeden" />
<Button Content="Dwa" />
</StackPanel>
✅ Jawnie ustawiony Orientation
<StackPanel Orientation="Horizontal"> <Button Content="Jeden" /> <Button Content="Dwa" /> </StackPanel>
❌ Błąd 3: Ustawianie Width=”*” w StackPanel
❌ * nie działa w StackPanel
<StackPanel Orientation="Horizontal">
<TextBox Width="*" />
<!-- Błąd! StackPanel nie
obsługuje * jak Grid -->
</StackPanel>
✅ Do tego potrzebny jest Grid
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" />
<Button Grid.Column="1"
Content="Szukaj" />
</Grid>
Zadania do wykonania
Stwórz okno z pionowym StackPanel zawierającym
5 przycisków: Poniedziałek, Wtorek, Środa, Czwartek, Piątek.
Każdy przycisk po kliknięciu wyświetla w TextBlock
(poza StackPanel) komunikat: „Wybrałeś: Środa”.
Przyciski mają mieć szerokość 150px i być wyśrodkowane.
Stwórz formularz logowania używając tylko StackPanel
(bez Grid): tytuł, etykieta + pole login, etykieta + pole hasło,
przycisk Zaloguj. Cały panel ma być wyśrodkowany na oknie
i mieć szerokość 260px.
Po kliknięciu „Zaloguj” sprawdź czy login to admin
i hasło to 1234 – wyświetl odpowiedni komunikat.
W zdarzeniu Window_Loaded dynamicznie wygeneruj
w C# listę 6 produktów (wymyśl je sam).
Każdy produkt to poziomy StackPanel z: nazwą produktu (TextBlock)
i przyciskiem „Dodaj do koszyka”. Po kliknięciu przycisku
nazwa produktu trafia do ListBox umieszczonego
obok panelu listy.
Zbuduj layout okna używając Grid + StackPanel:
- Grid z 3 wierszami: nagłówek (
Auto), treść (*), stopka (Auto) - W nagłówku: poziomy StackPanel z logo (TextBlock) po lewej i przyciskami nawigacji po prawej
- W treści: dowolna zawartość (np. duże pole TextBox)
- W stopce: poziomy StackPanel wyrównany do prawej z przyciskami „Anuluj” i „Zapisz”