Button – przycisk
Poznasz Button – najczęściej używaną kontrolkę interaktywną w WPF. Nauczysz się obsługiwać kliknięcia, tworzyć przyciski z ikonami, wyłączać je i dodawać podpowiedzi.
Czym jest Button?
Button to klikalny przycisk – jedna z najważniejszych kontrolek w każdej aplikacji okienkowej. Użytkownik klika, a Twój kod C# reaguje wykonując określoną akcję.
Wystarczy podać Content (treść) i podpiąć obsługę Click:
<Button Content="Kliknij mnie" Click="Przycisk_Click" />
private void Przycisk_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Kliknięto przycisk!"); }
Content – zawartość przycisku
Tekst jako Content
Najczęściej Content to po prostu tekst, podany jako atrybut.
<Button Content="Zapisz" Width="100" /> <Button Content="Anuluj" Width="100" /> <Button Content="Usuń" Width="100" />
Content jako dowolny element
Właściwość Content to nie tylko tekst – może przyjąć
dowolny element WPF. To znaczy, że przycisk może zawierać
obraz, kombinację tekstu i ikony, nawet cały StackPanel z kilkoma elementami.
<Button Width="140" Height="40"> <Button.Content> <StackPanel Orientation="Horizontal"> <TextBlock Text="💾" Margin="0,0,6,0" /> <TextBlock Text="Zapisz plik" /> </StackPanel> </Button.Content> </Button>
Button dziedziczy po ContentControl – klasie, która może
wyświetlić cokolwiek jako swoją zawartość. To ta sama
mechanika, dzięki której wewnątrz przycisku można umieścić obraz,
ikonę razem z tekstem, czy nawet animację.
Zdarzenie Click
Podpięcie w XAML
Są dwa sposoby podpięcia obsługi kliknięcia: wpisanie nazwy metody ręcznie w XAML, albo kliknięcie dwukrotne na przycisku w designerze Visual Studio (które zrobi to automatycznie).
<Button x:Name="btnZapisz" Content="Zapisz" Click="btnZapisz_Click" />
private void btnZapisz_Click(object sender, RoutedEventArgs e) { // Twój kod tutaj MessageBox.Show("Zapisano!"); }
sender to obiekt, który wywołał zdarzenie – w tym przypadku
klikany przycisk. e to dodatkowe informacje o zdarzeniu.
Najczęściej ich nie potrzebujesz, ale sender przydaje się
gdy kilka przycisków używa tej samej metody (patrz niżej).
Wspólna metoda dla wielu przycisków
Jeśli kilka przycisków ma podobną logikę, możesz podpiąć je
do tej samej metody i rozróżnić który został kliknięty
za pomocą sender.
<Button Content="Poniedziałek" Click="DzienTygodnia_Click" /> <Button Content="Wtorek" Click="DzienTygodnia_Click" /> <Button Content="Środa" Click="DzienTygodnia_Click" />
private void DzienTygodnia_Click(object sender, RoutedEventArgs e) { // Rzutujemy sender na Button, żeby odczytać który był kliknięty Button klikniety = (Button)sender; string dzien = klikniety.Content.ToString(); lblWynik.Text = $"Wybrano: {dzien}"; }
IsEnabled – włączanie i wyłączanie
IsEnabled kontroluje czy przycisk jest aktywny.
Wyłączony przycisk (IsEnabled="False") jest wyszarzony
i nie reaguje na kliknięcia.
<Button x:Name="btnWyslij" Content="Wyślij" IsEnabled="False" />
Najczęstszy wzorzec: przycisk jest wyłączony do momentu, gdy użytkownik wypełni wymagane pole.
// XAML: <TextBox x:Name="txtEmail" TextChanged="txtEmail_TextChanged" /> // <Button x:Name="btnWyslij" IsEnabled="False" /> private void txtEmail_TextChanged(object sender, TextChangedEventArgs e) { // Przycisk aktywny tylko gdy pole nie jest puste btnWyslij.IsEnabled = !string.IsNullOrWhiteSpace(txtEmail.Text); }
Inny częsty przypadek: wyłączenie przycisku po kliknięciu, żeby zapobiec wielokrotnemu wysłaniu tej samej akcji (np. wielokrotne zamówienie po szybkim klikaniu).
private void btnZamow_Click(object sender, RoutedEventArgs e) { btnZamow.IsEnabled = false; // blokujemy ponowne kliknięcie btnZamow.Content = "Przetwarzanie..."; // (tu logika zamówienia) MessageBox.Show("Zamówienie złożone!"); btnZamow.Content = "Zamów"; btnZamow.IsEnabled = true; }
IsEnabled="False" – przycisk jest widoczny,
ale wyszarzony i nieaktywny.
Visibility="Collapsed" – przycisk jest całkowicie niewidoczny,
jakby go nie było.
Wybierz IsEnabled, gdy chcesz pokazać użytkownikowi, że opcja istnieje,
ale jest niedostępna. Wybierz Visibility, gdy opcja ma być całkowicie skryta.
IsDefault i IsCancel – obsługa Enter i Esc
Te dwie właściwości pozwalają obsłużyć przycisk klawiaturą bez pisania żadnego kodu – działają automatycznie.
| Właściwość | Klawisz | Działanie |
|---|---|---|
IsDefault="True" | Enter | Naciśnięcie Enter w oknie „klika” ten przycisk |
IsCancel="True" | Esc | Naciśnięcie Esc w oknie „klika” ten przycisk |
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button Content="Anuluj" IsCancel="True" Width="80" Margin="0,0,8,0" Click="btnAnuluj_Click" /> <Button Content="OK" IsDefault="True" Width="80" Click="btnOK_Click" /> </StackPanel> <!-- Enter = kliknie OK, Esc = kliknie Anuluj – niezależnie od tego, który element ma focus -->
IsDefault ustawiaj na przycisku, który wykonuje
„pozytywną” akcję (OK, Zapisz, Zaloguj). IsCancel
na przycisku zamykającym/odwołującym (Anuluj, Zamknij).
Dzięki temu formularz da się obsłużyć w pełni klawiaturą –
ważne dla wygody i dostępności (accessibility).
ToolTip – podpowiedź po najechaniu
ToolTip to mały żółty komunikat, który pojawia się
po najechaniu kursorem na element i chwili oczekiwania.
Przydaje się do wyjaśniania znaczenia przycisków – zwłaszcza
tych z samą ikoną, bez tekstu.
<Button Content="🗑" Width="40" ToolTip="Usuń wybrany element" /> <Button Content="💾" Width="40" ToolTip="Zapisz zmiany (Ctrl+S)" />
ToolTip może też być złożonym elementem – nie tylko tekstem.
<Button Content="Eksportuj"> <Button.ToolTip> <StackPanel> <TextBlock Text="Eksport danych" FontWeight="Bold" /> <TextBlock Text="Zapisuje dane do pliku CSV" Foreground="Gray" /> </StackPanel> </Button.ToolTip> </Button>
Przycisk z ikoną
Emoji jako ikona – najprostszy sposób
Najprostszym sposobem dodania ikony jest użycie emoji w tekście. Nie wymaga żadnych plików graficznych i działa od razu.
<Button Content="➕ Dodaj" Width="100" /> <Button Content="🗑 Usuń" Width="100" /> <Button Content="✏️ Edytuj" Width="100" /> <Button Content="💾 Zapisz" Width="100" /> <Button Content="🔍 Szukaj" Width="100" /> <Button Content="⚙️ Ustawienia" Width="110" />
Obraz + tekst (Image + TextBlock)
Dla bardziej profesjonalnego wyglądu możesz użyć prawdziwego pliku graficznego razem z tekstem, łącząc je w StackPanel.
<Button Width="140" Height="40"> <StackPanel Orientation="Horizontal"> <Image Source="/Images/save.png" Width="20" Height="20" Margin="0,0,8,0" /> <TextBlock Text="Zapisz" VerticalAlignment="Center" /> </StackPanel> </Button>
Tylko ikona, bez tekstu – dobry do przycisków w toolbarach. Wtedy koniecznie dodaj ToolTip, żeby użytkownik wiedział co robi przycisk.
<Button Width="36" Height="36" ToolTip="Usuń wybrany element"> <Image Source="/Images/delete.png" Width="18" Height="18" /> </Button>
Wygląd przycisku
Podstawowy wygląd przycisku możesz dostosować bez wnikania w zaawansowane style i szablony (te poznasz w dalszych tematach).
<Button Content="Zapisz zmiany" Width="150" Height="40" Background="#2ecc71" Foreground="White" FontSize="14" FontWeight="Bold" BorderThickness="0" Cursor="Hand" />
| Właściwość | Co zmienia |
|---|---|
Background | Kolor tła przycisku |
Foreground | Kolor tekstu |
BorderBrush | Kolor obramowania |
BorderThickness | Grubość obramowania (0 = bez ramki) |
Padding | Wewnętrzny odstęp treści od krawędzi |
Cursor | Kształt kursora po najechaniu ("Hand" = łapka) |
Opacity | Przezroczystość (0.0 – 1.0) |
Przydatny zestaw kolorów dla przycisków akcji:
<Button Content="Zapisz" Background="#2ecc71" Foreground="White" /> <!-- zielony – sukces --> <Button Content="Usuń" Background="#e74c3c" Foreground="White" /> <!-- czerwony – niebezpieczna akcja --> <Button Content="Edytuj" Background="#3498db" Foreground="White" /> <!-- niebieski – neutralna akcja --> <Button Content="Anuluj" Background="#95a5a6" Foreground="White" /> <!-- szary – mniej istotna akcja --> <Button Content="Ostrzeżenie" Background="#f39c12" Foreground="White" /> <!-- pomarańcz – uwaga -->
Przyciski tworzone w C#
Tak jak inne kontrolki, Button możesz w pełni stworzyć i skonfigurować z kodu C#. Przydaje się to gdy liczba przycisków zależy od danych.
private void Window_Loaded(object sender, RoutedEventArgs e) { string[] kategorie = { "Elektronika", "Odzież", "Sport", "Książki" }; foreach (string kategoria in kategorie) { Button btn = new Button(); btn.Content = kategoria; btn.Width = 120; btn.Height = 35; btn.Margin = new Thickness(5); btn.Tag = kategoria; // zapamiętujemy kategorię btn.Click += Kategoria_Click; // podpinamy obsługę panelKategorii.Children.Add(btn); } } private void Kategoria_Click(object sender, RoutedEventArgs e) { Button klikniety = (Button)sender; string kategoria = (string)klikniety.Tag; lblWynik.Text = $"Wybrana kategoria: {kategoria}"; }
Zwróć uwagę na btn.Click += Kategoria_Click; – używamy
+=, nie =. To dlatego, że do jednego zdarzenia
można podpiąć wiele metod (choć w praktyce zwykle podpinamy jedną).
Operator = przy zdarzeniach w C# nie istnieje – kompilator zgłosi błąd.
Częste błędy
❌ Błąd 1: Literówka w nazwie metody Click
❌ Nazwa się nie zgadza
<!-- XAML: -->
<Button Click="btnZapisz_Click" />
// C#:
private void btnZapsiz_Click(...) // literówka!
{ }
// Błąd kompilacji
✅ Pozwól Visual Studio wygenerować
Kliknij dwukrotnie przycisk w designerze XAML – Visual Studio sam utworzy metodę z poprawną nazwą i podpięciem.
❌ Błąd 2: Zapominanie o sprawdzeniu null przy rzutowaniu sender
❌ Zbyt pewne rzutowanie
private void Wspolna_Click(object sender, ...)
{
Button btn = (Button)sender;
string tag = (string)btn.Tag;
// Jeśli Tag nie był ustawiony (null) –
// rzutowanie wyrzuci wyjątek!
}
✅ Sprawdzenie przed rzutowaniem
private void Wspolna_Click(object sender, ...)
{
Button btn = (Button)sender;
if (btn.Tag == null) return;
string tag = (string)btn.Tag;
}
❌ Błąd 3: Brak ToolTip na przycisku tylko z ikoną
❌ Niejasne znaczenie przycisku
<Button Content="🗑" Width="36" />
<!-- Co robi ten przycisk?
Użytkownik musi zgadywać -->
✅ ToolTip wyjaśnia funkcję
<Button Content="🗑" Width="36"
ToolTip="Usuń element" />
❌ Błąd 4: Niewyłączony przycisk podczas długiej operacji
❌ Można kliknąć wiele razy
private void btnWyslij_Click(...)
{
// Brak IsEnabled = false
// Użytkownik może kliknąć
// kilka razy zanim operacja się skończy
WyslijDane();
}
✅ Blokada na czas operacji
private void btnWyslij_Click(...)
{
btnWyslij.IsEnabled = false;
WyslijDane();
btnWyslij.IsEnabled = true;
}
Zadania do wykonania
Stwórz okno z trzema przyciskami: „➕ Dodaj”, „✏️ Edytuj”, „🗑 Usuń”, każdy w innym kolorze (zielony, niebieski, czerwony) z białym tekstem. Każdy ma ToolTip wyjaśniający jego funkcję. Kliknięcie każdego wyświetla odpowiedni MessageBox.
Stwórz formularz logowania: TextBox na login, PasswordBox na hasło,
przycisk „Zaloguj” z IsDefault="True" i przycisk
„Anuluj” z IsCancel="True".
Przycisk „Zaloguj” jest wyłączony (IsEnabled="False")
dopóki obydwa pola nie są wypełnione – użyj TextChanged
i PasswordChanged.
W C# dynamicznie wygeneruj 10 przycisków z liczbami 1-10
w WrapPanel. Każdy przycisk po kliknięciu dodaje swoją wartość
do sumy wyświetlanej w TextBlock. Dodaj przycisk „Reset”,
który zeruje sumę. Użyj wspólnej metody obsługującej
wszystkie przyciski z liczbami (rozróżniaj przez sender i Tag).
Stwórz prosty quiz z jednym pytaniem i czterema przyciskami odpowiedzi
(A, B, C, D). Po kliknięciu poprawnej odpowiedzi przycisk
natychmiast zmienia tło na zielone i wyświetla „Poprawnie!”.
Po kliknięciu błędnej – tło czerwone, wszystkie przyciski
się blokują (IsEnabled = false), a poprawna odpowiedź
też podświetla się na zielono.