Dataczwartek, 13 sierpnia 2026 Czas19:12:47
← Aplikacje desktopowe (WPF)

Lekcja 13. Modele danych i walidacja formularzy

Trudny / egzaminacyjny

Po co się tego uczymy?

Formularze w prawdziwych aplikacjach mają zwykle wiele pól, a dane z nich trzeba jakoś zorganizować i sprawdzić, zanim zostaną użyte. Ta lekcja łączy dwie powiązane umiejętności: tworzenie modeli danych (klas grupujących powiązane informacje) i walidację (sprawdzanie poprawności danych wpisanych przez użytkownika) — obie kluczowe dla solidnych aplikacji desktopowych.

Teoria

Wyobraź sobie aplikację "Formularz zdrowia", gdzie użytkownik wpisuje imię, wzrost, wagę i płeć. Można by trzymać te wartości w osobnych zmiennych rozsianych po kodzie — ale to bałagan. Znacznie lepiej stworzyć model, czyli klasę grupującą wszystkie powiązane dane w jednym obiekcie — jak teczka pacjenta w przychodni zamiast trzech luźnych karteczek.

Model powinien zawierać właściwości (properties) odpowiadające danym z formularza, i ewentualnie metody bezpośrednio związane z tymi danymi (np. ObliczBmi() w klasie modelu danych zdrowotnych). Model NIE powinien zawierać kodu obsługującego interfejs (np. MessageBox.Show) ani walidacji — to osobna odpowiedzialność (nawiązanie do zasady z poprzedniej lekcji o oddzieleniu logiki od UI).

Walidacja to sprawdzanie, czy dane wpisane przez użytkownika są poprawne i sensowne, ZANIM ich użyjemy. Typowe reguły: pole nie może być puste, liczba musi być większa od zera, wartość musi mieścić się w rozsądnym zakresie, wybór musi być jedną z dostępnych opcji. Dobra walidacja zabezpiecza przed błędami w działaniu programu (np. dzieleniem przez zero) i od razu informuje użytkownika, co wpisał źle, zamiast pozwolić programowi się "wywrócić".

Sensowna organizacja projektu z modelami i walidacją wygląda np. tak: folder Modele/ z klasami przechowującymi dane, folder Walidacja/ z klasami/metodami sprawdzającymi te dane, a MainWindow.xaml/.cs jako warstwa interfejsu, która korzysta z obu — dokładnie rozwijając ideę z poprzedniej lekcji.

Przykład z życia

Formularz rejestracji na dowolnej stronie czy w aplikacji: model DaneUzytkownika grupuje imię, email, hasło, datę urodzenia w jednym obiekcie zamiast osobnych zmiennych. Osobna klasa Walidator sprawdza każde pole (czy email ma poprawny format, czy hasło ma min. 8 znaków, czy użytkownik ma ukończone 13 lat) i zwraca listę konkretnych błędów do wyświetlenia — dokładnie tak, jak dzieje się to w każdym profesjonalnym formularzu, który widziałeś w internecie czy aplikacji mobilnej.

Kod (C#)

// Modele/DaneFormularza.cs - model grupujacy dane z formularza
namespace FormularzZdrowia.Modele
{
    public class DaneFormularza
    {
        public string Imie { get; set; } = "";
        public double WzrostCm { get; set; }
        public double WagaKg { get; set; }

        // Metoda ZWIAZANA z danymi modelu - to jest OK w modelu
        public double ObliczBmi()
        {
            double wzrostM = WzrostCm / 100.0;
            return WagaKg / (wzrostM * wzrostM);
        }
    }
}

// Walidacja/WalidatorFormularza.cs - osobna klasa sprawdzajaca dane
using System.Collections.Generic;
using FormularzZdrowia.Modele;

namespace FormularzZdrowia.Walidacja
{
    public class WalidatorFormularza
    {
        public List<string> Sprawdz(DaneFormularza dane)
        {
            var bledy = new List<string>();

            if (string.IsNullOrWhiteSpace(dane.Imie))
            {
                bledy.Add("Imie nie moze byc puste.");
            }
            if (dane.WzrostCm <=  || dane.WzrostCm > 250)
            {
                bledy.Add("Wzrost musi byc liczba z zakresu 1-250 cm.");
            }
            if (dane.WagaKg <=  || dane.WagaKg > 300)
            {
                bledy.Add("Waga musi byc liczba z zakresu 1-300 kg.");
            }

            return bledy; // pusta lista = dane sa poprawne
        }
    }
}

// MainWindow.xaml.cs - fragment uzycia obu klas
private void PrzyciskOblicz_Click(object sender, RoutedEventArgs e)
{
    var dane = new DaneFormularza
    {
        Imie = PoleImie.Text,
        WzrostCm = double.TryParse(PoleWzrost.Text, out var w) ? w : ,
        WagaKg = double.TryParse(PoleWaga.Text, out var m) ? m : 
    };

    var walidator = new WalidatorFormularza();
    var bledy = walidator.Sprawdz(dane);

    if (bledy.Count > )
    {
        EtykietaWynik.Text = "Bledy: " + string.Join(" ", bledy);
        return;
    }

    EtykietaWynik.Text = $"BMI dla {dane.Imie}: {dane.ObliczBmi():F1}";
}

Komentarz i wyjaśnienie kodu

DaneFormularza to prosty model — trzy właściwości i jedna metoda (ObliczBmi) bezpośrednio związana z tymi danymi. Model NIE wie nic o polach tekstowych ani oknie — to zwykła klasa C#.

WalidatorFormularza.Sprawdz przyjmuje gotowy obiekt modelu i zwraca LISTĘ błędów (pustą, jeśli wszystko jest poprawne) — dzięki zwróceniu listy, a nie pojedynczego bool, można pokazać użytkownikowi WSZYSTKIE problemy naraz, zamiast tylko pierwszego napotkanego.

W code-behind okna: najpierw budujemy obiekt modelu z danych wpisanych przez użytkownika (double.TryParse bezpiecznie próbuje zamienić tekst na liczbę, zwracając 0 jeśli się nie uda — to zapobiega awarii przy niepoprawnym wpisie), potem wołamy walidator, i dopiero jeśli lista błędów jest pusta, wykonujemy właściwe obliczenie przez dane.ObliczBmi().

Ćwiczenie samodzielne

Utwórz projekt z folderami Modele i Walidacja, wklej powyższe klasy, zbuduj prosty formularz z polami Imię/Wzrost/Waga i przyciskiem "Oblicz BMI", i sprawdź działanie zarówno dla poprawnych, jak i błędnych danych (np. wzrost = 0, puste imię).

Zadania do pracy własnej

  1. Rozbuduj WalidatorFormularza o sprawdzenie, czy imię ma przynajmniej 2 znaki i nie zawiera cyfr.

  2. Stwórz model DaneZamowienia (nazwa produktu, ilość, cena jednostkowa) z metodą ObliczWartoscCalkowita(), oraz osobny WalidatorZamowienia sprawdzający, że ilość i cena są dodatnimi liczbami, a nazwa produktu nie jest pusta.

  3. Zaprojektuj formularz rejestracji z modelem DaneUzytkownika (login, hasło, powtórz hasło, wiek) i walidatorem sprawdzającym: login min. 3 znaki, hasło min. 8 znaków, hasła identyczne, wiek między 13 a 120 lat. Wyświetl WSZYSTKIE błędy naraz w jednej etykiecie (każdy w nowej linii), a po poprawnych danych pokaż komunikat sukcesu.

Typowe błędy

Umieszczanie logiki UI (np. MessageBox.Show) wewnątrz klasy modelu lub walidatora — łamie zasadę oddzielenia z poprzedniej lekcji; walidator powinien tylko ZWRACAĆ informację o błędach, a to okno decyduje, jak je pokazać.

Sprawdzanie tylko pierwszego błędu i przerywanie walidacji — użytkownik poprawia jedno pole, klika ponownie, i widzi KOLEJNY błąd, którego wcześniej nie było widać — frustrujące doświadczenie. Lepiej zbierać wszystkie błędy naraz (jak w przykładzie z listą).

Brak zabezpieczenia przy konwersji tekstu na liczbę — bezpośrednie użycie double.Parse(PoleWzrost.Text) bez TryParse spowoduje awarię programu, jeśli użytkownik wpisze coś, co nie jest liczbą (np. literki).

Nawiązanie do egzaminu zawodowego

To rozwinięcie INF.04.5.3 w kontekście projektowania solidnego interfejsu formularza oraz naturalne połączenie z zasadami programowania obiektowego z działu "Programowanie konsolowe" (klasy, właściwości, hermetyzacja) — modele danych to nic innego, jak zwykłe klasy C#, których użycie poznałeś już wcześniej.