Aplikacje desktopowe · Kontrolki I

Button, TextBox i TextBlock: trzy kontrolki każdego formularza

Przycisk, pole tekstowe i etykieta pojawią się w prawie każdym zadaniu egzaminacyjnym. Poznasz ich najważniejsze właściwości, odpowiedniki w Windows Forms i zbudujesz formularz, który reaguje na każdą wpisaną literę.

  • około 45 minut
  • WPF · Button · TextBox · TextBlock
  • INF.04.5.3

Po tej lekcji: ustawić podstawowe właściwości przycisku, pola tekstowego i etykiety, odczytać wpisany tekst oraz zareagować na jego zmianę zdarzeniem TextChanged.

Zacznijmy od pytania

„Ile właściwości ma przycisk?”

Każda kontrolka w WPF ma dziesiątki właściwości. Nie musisz znać ich wszystkich na pamięć, ale warto wiedzieć, które są używane w niemal każdej aplikacji, i gdzie szukać reszty (okno Properties w Visual Studio).

Na egzaminie pojawia się czasem pytanie o odpowiednik w Windows Forms, dlatego przy każdej kontrolce zobaczysz obie nazwy.

1 · Przycisk

Najważniejsze właściwości Button

WPFWindows FormsCo robi
ContentTextNapis na przycisku (w WPF może to być nawet obrazek).
IsEnabledEnabledfalse wyszarza przycisk i blokuje kliknięcie.
VisibilityVisibleVisible, Hidden (niewidoczny, ale zajmuje miejsce) albo Collapsed (znika całkiem).
BackgroundBackColorKolor tła.
ForegroundForeColorKolor tekstu.
FontSize, FontWeight, FontFamilyFontRozmiar i styl czcionki. W Forms to jeden obiekt.
Width, HeightWidth, HeightWymiary w pikselach niezależnych od rozdzielczości.
Command—Alternatywa dla Click: łączy przycisk z metodą w ViewModelu (MVVM).
Napis na przycisku w WPF to `Content`, a nie `Text`. To najczęstsza wpadka osób znających Windows Forms.

2 · Pole tekstowe

Najważniejsze właściwości TextBox

WPFWindows FormsCo robi
TextTextZawartość pola (string), którą wpisuje użytkownik.
MaxLengthMaxLengthMaksymalna liczba znaków.
AcceptsReturn + większa wysokośćMultilinePozwala pisać w wielu liniach.
IsReadOnlyReadOnlyUżytkownik widzi tekst, ale go nie zmieni.
osobna kontrolka PasswordBoxPasswordCharUkrywa znaki hasła. W WPF to inna kontrolka, nie właściwość.
TextWrapping(automatyczne)Zawijanie tekstu w polu wielowierszowym.
W większych aplikacjach tekst z `TextBox` łączy się z danymi przez wiązanie (`{Binding}`). Tutaj poznajesz prostszy sposób, oparty na zdarzeniach.

3 · Wyświetlanie tekstu

Dwie kontrolki do napisów, jedna częściej używana

TextBlocklekki napis

Najczęstszy wybór do wyświetlania tekstu, którego użytkownik nie edytuje. Napis ustawiasz we właściwości **Text**. Rozmiar dopasowuje się sam.

Na przykład EtykietaWynik.Text = "Gotowe";

Labelpodpis przy kontrolce

Cięższa kontrolka, używana głównie jako podpis pola (ma właściwość Target). Napis ustawiasz we właściwości **Content**.

Na przykład PodpisImie.Content = "Imię:";

Laboratorium · ćwiczenie w przeglądarce, do którego odsyłają rozgrzewki na końcu lekcji

4 · Sprawdź w działaniu

Formularz, który reaguje na każdą literę

Wpisz imię w polu tekstowym. Zobacz, jak licznik zmienia się przy każdym znaku, a przycisk włącza się dopiero, gdy coś wpiszesz. Potem otwórz zakładkę .cs, zmień warunek (np. dlugosc > 2) i sprawdź efekt.

Ta interakcja wymaga włączonego JavaScriptu.

TextChanged wywoła się przy każdej zmianie tekstu. Dobre miejsce na liczniki, podpowiedzi i włączanie przycisków.

5 · Wygląd

MainWindow.xaml

Każda kontrolka, do której będziesz się odwoływać z kodu C#, **musi mieć x:Name**. Pozostałe elementy (jak tekst „Podaj swoje imię:”) nie potrzebują nazwy.

MainWindow.xamlxaml
<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="260" 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>
  1. MaxLength="30" Użytkownik nie wpisze więcej niż 30 znaków.
  2. TextChanged="PoleImie_TextChanged" Podpięcie metody do zdarzenia zmiany tekstu.
  3. IsEnabled="False" Przycisk startuje wyłączony. Włączy go dopiero kod C#.
  4. FontWeight="Bold" i Foreground="DarkGreen" Pogrubienie i kolor zielony wyniku.

6 · Działanie

MainWindow.xaml.cs

Dwie metody: jedna reaguje na zmianę tekstu, druga na kliknięcie. Nazwy muszą dokładnie odpowiadać tym z XAML.

MainWindow.xaml.cscsharp
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 włącza się dopiero, gdy użytkownik coś wpisał
        PrzyciskPrzywitaj.IsEnabled = dlugosc > 0;
    }

    private void PrzyciskPrzywitaj_Click(object sender, RoutedEventArgs e)
    {
        EtykietaWynik.Text = $"Witaj, {PoleImie.Text}!";
    }
}
  1. PoleImie.Text.Length Długość wpisanego tekstu, czyli liczba znaków.
  2. $"Długość: {dlugosc} znaków" Napis z wstawioną wartością zmiennej w klamrach (interpolacja).
  3. IsEnabled = dlugosc > 0 Wyrażenie logiczne wprost jako wartość: przycisk jest włączony, gdy wpisano co najmniej jeden znak.
  4. $"Witaj, {PoleImie.Text}!" Powitanie z tekstem pobranym z pola.

Do zadań

Włączanie przycisku, TryParse i kolor etykiety

Zadania łączą trzy rzeczy: przycisk aktywny dopiero po wypełnieniu pól, zamianę wieku na liczbę oraz kolory. Kolory z kodu znasz z lekcji o pierwszej aplikacji (Brushes).

MainWindow.xaml.cscsharp
using System.Windows.Media;   // Brushes

// XAML: <TextBox x:Name="PoleImie" TextChanged="Pole_TextChanged" />  (to samo w pozostałych polach)
private void Pole_TextChanged(object sender, TextChangedEventArgs e)
{
    if (PrzyciskZarejestruj == null) return;     // zdarzenie odpala się już podczas wczytywania okna

    PrzyciskZarejestruj.IsEnabled =
        !string.IsNullOrWhiteSpace(PoleImie.Text) &&
        !string.IsNullOrWhiteSpace(PoleNazwisko.Text) &&
        !string.IsNullOrWhiteSpace(PoleWiek.Text);
}

private void PrzyciskZarejestruj_Click(object sender, RoutedEventArgs e)
{
    if (int.TryParse(PoleWiek.Text, out int wiek))
    {
        Podsumowanie.Foreground = Brushes.Black;
        Podsumowanie.Text = $"{PoleImie.Text} {PoleNazwisko.Text}, {wiek} lat";
    }
    else
    {
        Podsumowanie.Foreground = Brushes.Red;
        Podsumowanie.Text = "Wiek musi być liczbą całkowitą.";
    }
}

// Kolor tła etykiety
EtykietaWynik.Background = Brushes.LightGreen;
EtykietaWynik.Background = Brushes.Transparent;   // przywrócenie braku tła
  1. TextChanged Zdarzenie odpala się przy każdej zmianie tekstu. Jedną metodę możesz podpiąć pod wiele pól.
  2. int.TryParse(tekst, out int wiek) Zwraca true, gdy tekst jest liczbą, i wtedy zapisuje ją do wiek. Przy „abc” zwraca false i program się nie wywraca.
  3. IsEnabled false wyszarza kontrolkę i blokuje kliknięcie.

7 · Czego unikać

Cztery wpadki z formularzami

Brak `x:Name` na kontrolce
Tak nie
<TextBox />

// w C#:
string imie = PoleImie.Text;

Błąd CS0103: nazwa „PoleImie” nie istnieje w bieżącym kontekście.

Tak
<TextBox x:Name="PoleImie" />

// w C#:
string imie = PoleImie.Text;

Bez x:Name kontrolka nie ma nazwy w kodzie.

Literówka w nazwie metody
Tak nie
<Button Click="PrzyciskZapisz_Clik" />

Program się nie skompiluje: w klasie nie ma takiej metody.

Tak
<Button Click="PrzyciskZapisz_Click" />

Nazwa w XAML musi być identyczna z nazwą metody w C#.

`Text` na przycisku
Tak nie
PrzyciskZapisz.Text = "OK";

Błąd kompilatora: Button nie zawiera definicji „Text”.

Tak
PrzyciskZapisz.Content = "OK";

Przycisk WPF trzyma napis w Content. Text jest w Windows Forms.

Oczekiwanie reakcji „na żywo” z wiązania
Tak nie
<TextBox Text="{Binding Imie}" />

Właściwość Imie zmienia się dopiero po utracie fokusu przez pole.

Tak
<TextBox Text="{Binding Imie, UpdateSourceTrigger=PropertyChanged}" />

Domyślnie TextBox aktualizuje źródło danych po wyjściu z pola. Reakcję przy każdym znaku włączysz jawnie.

8 · Sprawdź się

Dobierz właściwość do zadania

Cztery krótkie sytuacje z formularzem.

Ta interakcja wymaga włączonego JavaScriptu.

Podsumowanie

Co warto zapamiętać

  1. Button: napis w Content, wyłączenie przez IsEnabled, widoczność przez Visibility.
  2. TextBox: tekst w Text, limit w MaxLength, hasła w osobnej kontrolce PasswordBox.
  3. TextBlock wyświetla napis (Text), a Label to podpis (Content).
  4. TextChanged wywołuje się przy każdej zmianie tekstu.
  5. Kontrolka używana w kodzie musi mieć x:Name, a nazwy metod w XAML i C# muszą być identyczne.

Dalej na swoim koncie

Rozgrzewki, quiz i zadania są w biurku ucznia.

Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.

Zaloguj się →
Źródła i dalsza nauka