Lekcja 6. Kontrolki I — Button, TextBox, Label/TextBlock
ŚredniPo co się tego uczymy?
"Taki Button — ile ma właściwości?" To pytanie, na które ta lekcja odpowiada wyczerpująco: poznasz PEŁNY zestaw właściwości trzech najczęściej używanych kontrolek — przycisku, pola tekstowego i etykiety — razem z ich odpowiednikami w Windows Forms (bo egzamin INF.04 może odwoływać się do obu technologii). To realizacja INF.04.5.3 ("programuje desktopowe aplikacje z wykorzystaniem kontrolek").
Teoria
W WPF każda kontrolka ma dziesiątki właściwości — nie musisz znać wszystkich na pamięć, ale musisz wiedzieć, gdzie szukać (okno Properties z poprzedniej lekcji) i jakie są te najważniejsze, używane praktycznie w każdej aplikacji.
Button (WPF) / Button (Windows Forms) — przycisk
| Właściwość WPF | Odpowiednik Windows Forms | Opis |
|---|---|---|
Content |
Text |
Tekst (lub dowolna zawartość — w WPF nawet obrazek) wyświetlany na przycisku. |
IsEnabled |
Enabled |
Włącza (true) lub wyłącza (false, przycisk wyszarzony i nieklikalny) przycisk. |
Visibility |
Visible |
W WPF przyjmuje wartość Visible, Hidden (niewidoczny, ale zajmuje miejsce) albo Collapsed (niewidoczny, nie zajmuje miejsca). W Forms to prosta wartość logiczna. |
Background |
BackColor |
Kolor tła przycisku. |
Foreground |
ForeColor |
Kolor tekstu. |
FontSize, FontWeight, FontFamily |
Font |
Styl i rozmiar czcionki (w WPF rozbite na osobne właściwości, w Forms jeden obiekt Font). |
Width, Height |
Width, Height |
Wymiary przycisku w pikselach niezależnych od rozdzielczości. |
Command |
— (brak odpowiednika) | Alternatywa dla zdarzenia Click — łączy przycisk z metodą w ViewModelu zamiast w code-behind. Poznasz szczegółowo w lekcji o obsłudze zdarzeń i w dziale MVVM. |
Obsługa kliknięcia w Windows Forms wygląda tak:
private void btnZapisz_Click(object sender, EventArgs e)
{
labelWynik.Text = "Dane zapisane!";
}
TextBox (WPF i Windows Forms) — pole tekstowe
| Właściwość WPF | Odpowiednik Windows Forms | Opis |
|---|---|---|
Text |
Text |
Zawartość pola — string, który wpisuje użytkownik. |
MaxLength |
MaxLength |
Maksymalna liczba znaków, jaką można wpisać. |
AcceptsReturn + wysokość > 1 wiersza |
Multiline |
Pozwala pisać tekst w kilku liniach zamiast jednej. |
IsReadOnly |
ReadOnly |
Pole tylko do odczytu — użytkownik widzi tekst, ale nie może go zmienić. |
osobna kontrolka PasswordBox |
PasswordChar |
Ukrywanie wpisywanych znaków (hasła). W WPF to CAŁKOWICIE inna kontrolka, nie właściwość TextBoxa. |
TextWrapping |
(automatyczne przy Multiline) | Zawijanie tekstu w polu wielowierszowym. |
W WPF pole tekstowe najczęściej łączy się z danymi przez data binding, zamiast ręcznie odczytywać Text przy każdym kliknięciu:
<TextBox Text="{Binding Imie, UpdateSourceTrigger=PropertyChanged}" />
Do pełnego bindingu (aktualizacja obiektu w tle na bieżąco) wrócimy przy okazji MVVM — w tej lekcji budujemy prostszą wersję, opartą na zdarzeniach, którą i tak musisz znać, bo bywa szybsza w małych aplikacjach.
Label / TextBlock — wyświetlanie tekstu
W WPF do wyświetlania tekstu (bez możliwości edycji przez użytkownika) służy najczęściej TextBlock — lżejsza kontrolka niż odziedziczony po Windows Forms Label (WPF też ma swój Label, używany rzadziej, głównie jako podpis obok innej kontrolki, np. z ustawionym Target).
| Właściwość WPF (TextBlock) | Odpowiednik Windows Forms (Label) | Opis |
|---|---|---|
Text |
Text |
Wyświetlany tekst. |
| (rozmiar dopasowuje się automatycznie) | AutoSize |
W Forms trzeba jawnie włączyć dopasowanie rozmiaru etykiety do treści — w WPF to zachowanie domyślne. |
Foreground |
ForeColor |
Kolor tekstu. |
Background |
BackColor |
Kolor tła. |
FontSize, FontWeight |
Font, TextAlign |
Styl czcionki i (w Forms) wyrównanie tekstu wewnątrz etykiety. |
TextWrapping |
(zależne od AutoSize) | Zawijanie długiego tekstu do kolejnej linii. |
Przykład w Windows Forms — ustawienie tekstu etykiety z kodu: lblWynik.Text = "Witaj, " + txtImie.Text + "!"; W WPF ten sam efekt osiąga się albo przez binding (<TextBlock Text="{Binding Wynik}" />), albo — w prostszym, event-based podejściu tej lekcji — bezpośrednim przypisaniem w code-behind, identycznie jak w Forms.
Schemat
Mapa wlasciwosci: WPF -> Windows Forms Button: Content -> Text | IsEnabled -> Enabled | Visibility -> Visible Background -> BackColor | Foreground -> ForeColor TextBox: Text -> Text | MaxLength -> MaxLength | IsReadOnly -> ReadOnly PasswordBox (osobna kontrolka) -> PasswordChar TextBlock / Label: Text -> Text | Foreground -> ForeColor | Background -> BackColor
Przykład z życia
Formularz kontaktowy na stronie internetowej (imię, e-mail, przycisk "Wyślij") to dokładnie ten sam zestaw kontrolek co w aplikacji desktopowej — pole tekstowe do wpisania danych, etykieta pokazująca wynik lub błąd walidacji, przycisk uruchamiający akcję. Różni się tylko technologia (HTML zamiast XAML), ale koncepcja "kontrolka ma właściwości, które ustawiasz, i zdarzenia, na które reagujesz" jest uniwersalna w każdym interfejsie graficznym — również tym, który znasz z INF.03.
MainWindow.xaml
<Window x:Class="KontrolkiApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Formularz powitania" Height="220" Width="360">
<StackPanel Margin="20">
<TextBlock Text="Podaj swoje imię:" Margin="0,0,0,5"/>
<TextBox x:Name="PoleImie"
MaxLength="30"
TextChanged="PoleImie_TextChanged"/>
<TextBlock x:Name="EtykietaLicznik"
Text="Długość: 0 znaków"
Foreground="Gray"
Margin="0,5,0,15"/>
<Button x:Name="PrzyciskPrzywitaj"
Content="Przywitaj się"
IsEnabled="False"
Click="PrzyciskPrzywitaj_Click"/>
<TextBlock x:Name="EtykietaWynik"
Text=""
FontSize="16"
FontWeight="Bold"
Foreground="DarkGreen"
Margin="0,15,0,0"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace KontrolkiApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void PoleImie_TextChanged(object sender, TextChangedEventArgs e)
{
int dlugosc = PoleImie.Text.Length;
EtykietaLicznik.Text = $"Długość: {dlugosc} znaków";
// Przycisk wlacza sie dopiero, gdy uzytkownik cos wpisal
PrzyciskPrzywitaj.IsEnabled = dlugosc > ;
}
private void PrzyciskPrzywitaj_Click(object sender, RoutedEventArgs e)
{
EtykietaWynik.Text = $"Witaj, {PoleImie.Text}!";
}
}
}
Komentarz i wyjaśnienie kodu
Plik MainWindow.xaml definiuje sam wygląd — pole tekstowe z limitem 30 znaków (MaxLength), etykietę pokazującą licznik znaków, przycisk startowo wyłączony (IsEnabled="False") i etykietę na wynik. Zwróć uwagę, że każda kontrolka, do której chcemy się odwołać w kodzie C#, MUSI mieć nadane x:Name — to jest dokładnie ten identyfikator, po którym odwołujemy się do niej w pliku .xaml.cs.
Plik MainWindow.xaml.cs zawiera dwie metody obsługi zdarzeń. PoleImie_TextChanged uruchamia się przy KAŻDEJ zmianie tekstu w polu (czyli przy każdym wciśniętym klawiszu) — aktualizuje licznik znaków i włącza przycisk, gdy pole nie jest puste. PrzyciskPrzywitaj_Click uruchamia się po kliknięciu i wypisuje spersonalizowane powitanie. Zauważ, że w XAML nazwy tych metod (TextChanged="PoleImie_TextChanged", Click="PrzyciskPrzywitaj_Click") muszą DOKŁADNIE odpowiadać nazwom metod w code-behind — literówka tutaj to jeden z najczęstszych błędów początkujących.
Ćwiczenie samodzielne
Utwórz nowy projekt WPF, wklej powyższy XAML do MainWindow.xaml i kod C# do MainWindow.xaml.cs (pamiętaj, żeby zmienić x:Class na nazwę Twojego projektu). Uruchom aplikację, wpisz swoje imię i sprawdź, czy licznik znaków aktualizuje się na bieżąco, a przycisk włącza się dopiero po wpisaniu choć jednej litery.
Zadania do pracy własnej
Dodaj drugie pole TextBox (Nazwisko) i rozbuduj powitanie, żeby wyświetlało zarówno imię, jak i nazwisko.
Dodaj do formularza właściwość Background zmieniającą kolor tła EtykietaWynik na jasnozielony w momencie wyświetlenia powitania (ustaw tę właściwość w kodzie C#, w metodzie PrzyciskPrzywitaj_Click).
Zbuduj formularz rejestracji z trzema polami TextBox (Imię, Nazwisko, Wiek) i przyciskiem 'Zarejestruj'. Przycisk ma być IsEnabled="False" dopóki WSZYSTKIE trzy pola nie są wypełnione (podpięcie TextChanged pod każde z trzech pól, sprawdzające ich łączny stan). Po kliknięciu wyświetl podsumowanie w TextBlock, a pole Wiek spróbuj sparsować przez int.TryParse — jeśli się nie uda, pokaż czerwony komunikat błędu zamiast podsumowania.
Typowe błędy
Brak x:Name na kontrolce — bez tego atrybutu nie da się odwołać do kontrolki z kodu C#, kompilator zgłosi błąd "nie istnieje w bieżącym kontekście".
Niezgodność nazwy metody w XAML i code-behind — jeśli w Click="PrzyciskZapisz_Click" jest literówka względem nazwy metody w pliku .cs, aplikacja się nie skompiluje.
Mylenie Content (WPF) z Text — początkujący często próbują ustawić Text="OK" na przycisku (co jest poprawne w Windows Forms), podczas gdy w WPF przycisk używa właściwości Content.
Zapominanie o UpdateSourceTrigger przy bindingu — domyślnie TextBox aktualizuje powiązaną właściwość dopiero po utracie fokusu, nie przy każdym znaku — jeśli oczekujesz reakcji "na żywo", trzeba jawnie dodać UpdateSourceTrigger=PropertyChanged.
Nawiązanie do egzaminu zawodowego
To realizacja INF.04.5.3 — "programuje desktopowe aplikacje okienkowe z wykorzystaniem kontrolek". Button, TextBox i TextBlock/Label to absolutny fundament każdego formularza WPF — pojawią się w praktycznie każdym kolejnym zadaniu w tym dziale.