Dataczwartek, 13 sierpnia 2026 Czas18:47:35
← Aplikacje desktopowe (WPF)

Lekcja 10. Okna i dialogi — modalne, niemodalne i MessageBox

Średni

Po co się tego uczymy?

Prawdziwe aplikacje rzadko mają tylko jedno okno — potrzebne są okna dialogowe do potwierdzeń, ustawień, formularzy szczegółów. Podstawa programowa (INF.04.5.3) wymaga wprost umiejętności pracy z oknem/dialogiem modalnym i niemodalnym — ta lekcja pokazuje, kiedy i jak ich używać.

Teoria

Okno modalne (ang. modal) blokuje interakcję z resztą aplikacji, dopóki nie zostanie zamknięte — użytkownik MUSI je obsłużyć (np. kliknąć OK/Anuluj), zanim wróci do głównego okna. Otwiera się metodą ShowDialog(). Typowe zastosowanie: okno "Zapisz zmiany przed zamknięciem?", formularz edycji szczegółów rekordu.

Okno niemodalne (ang. modeless/non-modal) pozwala dalej korzystać z głównego okna, mimo że dodatkowe okno jest otwarte — oba działają niezależnie. Otwiera się metodą Show(). Typowe zastosowanie: panel narzędzi, podgląd na żywo, okno pomocy, które chcemy mieć otwarte obok głównej pracy.

MessageBox to gotowa, wbudowana klasa do szybkich, prostych komunikatów (informacja, ostrzeżenie, pytanie tak/nie) — nie trzeba projektować własnego okna. Wywołuje się statyczną metodą MessageBox.Show(tekst, tytul, przyciski, ikona), a wynik (który przycisk kliknął użytkownik) sprawdza się przez porównanie z wartościami MessageBoxResult (np. MessageBoxResult.Yes).

Żeby przekazać dane MIĘDZY oknami (np. wynik formularza z okna dialogowego z powrotem do okna głównego), tworzy się w drugim oknie publiczną właściwość, ustawia się ją przed zamknięciem okna, a w oknie głównym odczytuje się ją PO wywołaniu ShowDialog() (bo dopiero wtedy program "czeka", aż użytkownik zamknie okno modalne).

Schemat

Okno modalne (ShowDialog) vs niemodalne (Show):

MODALNE:                          NIEMODALNE:
Okno glowne  Okno dialogowe        Okno glowne  Okno pomocnicze
[zablokowane] <--- aktywne          [aktywne]     [tez aktywne]
     |                                   |              |
     |  czeka...                        moga dzialac jednoczesnie,
     |                                   przelaczanie miedzy nimi
     v (dopiero po zamknieciu)          swobodne
[znow aktywne]

Przykład z życia

Kiedy w edytorze tekstu próbujesz zamknąć dokument z niezapisanymi zmianami, pojawia się okno modalne "Czy zapisać zmiany?" — nie możesz kliknąć nic innego w aplikacji, dopóki nie odpowiesz. Z kolei panel "Znajdź i zamień" w wielu edytorach jest oknem niemodalnym — możesz przełączać się między nim a dokumentem, przewijać tekst, i wracać do wyszukiwania bez zamykania panelu.

Kod (C#)

// MainWindow.xaml.cs - otwieranie okna dialogowego i odczyt wyniku
using System.Windows;

namespace OknaApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void PrzyciskEdytuj_Click(object sender, RoutedEventArgs e)
        {
            OknoEdycji okno = new OknoEdycji();
            okno.ImieDoEdycji = EtykietaImie.Text; // przekazanie danych DO okna

            bool? wynik = okno.ShowDialog(); // program CZEKA tutaj, az uzytkownik zamknie okno

            if (wynik == true) // uzytkownik kliknal "Zapisz" w oknie dialogowym
            {
                EtykietaImie.Text = okno.ImieDoEdycji; // odczyt danych PO zamknieciu
            }
        }

        private void PrzyciskUsun_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult wynik = MessageBox.Show(
                "Czy na pewno chcesz usunac ten rekord?",
                "Potwierdzenie",
                MessageBoxButton.YesNo,
                MessageBoxImage.Warning
            );

            if (wynik == MessageBoxResult.Yes)
            {
                EtykietaImie.Text = "(usunieto)";
            }
        }

        private void PrzyciskPomoc_Click(object sender, RoutedEventArgs e)
        {
            OknoPomocy okno = new OknoPomocy();
            okno.Show(); // niemodalne - mozna dalej korzystac z okna glownego
        }
    }
}

Komentarz i wyjaśnienie kodu

PrzyciskEdytuj_Click tworzy nowe okno (OknoEdycji), ustawia jego publiczną właściwość ImieDoEdycji jeszcze przed pokazaniem, a potem wywołuje ShowDialog() — ta metoda ZWRACA WARTOŚĆ dopiero, gdy okno zostanie zamknięte, więc kod poniżej (odczyt okno.ImieDoEdycji) wykona się dopiero po zamknięciu. Sprawdzenie wynik == true pozwala rozróżnić, czy użytkownik kliknął "Zapisz" (ustawia w oknie dialogowym DialogResult = true) czy "Anuluj".

PrzyciskUsun_Click pokazuje typowe użycie MessageBox do potwierdzenia niebezpiecznej akcji — MessageBoxButton.YesNo pokazuje dwa przyciski, a wynik porównuje się z MessageBoxResult.Yes, żeby wykonać usunięcie tylko po potwierdzeniu.

PrzyciskPomoc_Click pokazuje okno NIEMODALNE przez Show() — program NIE czeka, wykonanie leci dalej natychmiast, a użytkownik może swobodnie przełączać się między oknem głównym a oknem pomocy.

Ćwiczenie samodzielne

Utwórz drugie okno w projekcie (Dodaj → Okno... w Visual Studio), dodaj mu publiczną właściwość typu string, i otwórz je jako modalne z głównego okna, przekazując i odczytując wartość dokładnie jak w przykładzie.

Zadania do pracy własnej

  1. Dodaj przycisk "O programie", który pokazuje MessageBox z nazwą aplikacji, wersją i Twoim imieniem jako autora (tylko przycisk OK, ikona informacyjna).

  2. Zbuduj okno modalne "Dodaj produkt" z polami Nazwa i Cena, przyciskami Zapisz/Anuluj (Zapisz ustawia DialogResult = true i zamyka okno, Anuluj ustawia false), i wyświetl dodany produkt na liście w oknie głównym po zamknięciu dialogu z wynikiem pozytywnym.

  3. Zbuduj aplikację z oknem głównym (lista zadań) i oknem niemodalnym "Statystyki" pokazującym na bieżąco liczbę zadań — okno statystyk powinno się automatycznie odświeżać (np. przez zdarzenie albo prosty timer) za każdym razem, gdy w oknie głównym dodasz lub usuniesz zadanie, mimo że oba okna są otwarte jednocześnie.

Typowe błędy

Użycie Show() tam, gdzie potrzebne jest ShowDialog() (i odwrotnie) — jeśli otworzysz okno przez Show() i od razu spróbujesz odczytać dane, które użytkownik dopiero wpisze, dostaniesz puste/nieaktualne wartości, bo program nie zaczekał na zamknięcie okna.

Otwieranie tego samego okna modalnego wielokrotnie bez sprawdzenia stanu — może prowadzić do wielu identycznych okien nałożonych na siebie, jeśli nie ma odpowiedniego zabezpieczenia.

Zapominanie o ustawieniu DialogResult w oknie dialogowym — bez tego ShowDialog() zwróci null zamiast jednoznacznego true/false, co utrudnia sprawdzenie, czy użytkownik zaakceptował, czy anulował.

Nawiązanie do egzaminu zawodowego

To realizacja INF.04.5.3 — "okno/dialog modalny/niemodalny/kontrolki... okna dialogowe". Znajomość różnicy między Show() a ShowDialog() to jedno z najczęściej sprawdzanych zagadnień w zadaniach egzaminacyjnych z aplikacją wieloOkienkową.