Aplikacje desktopowe · Okna
Okna i dialogi: modalne, niemodalne i MessageBox
Prawdziwe aplikacje rzadko mają jedno okno. Potrzebne są potwierdzenia, ustawienia i formularze szczegółów. Zobaczysz, czym różni się ShowDialog() od Show(), kiedy program czeka, a kiedy leci dalej, i jak przekazać dane między oknami.
- około 45 minut
- WPF · ShowDialog · MessageBox
- INF.04.5.3
Po tej lekcji: otworzyć okno modalne i niemodalne, odczytać wynik dialogu (DialogResult), użyć MessageBox z przyciskami Tak i Nie oraz przekazać dane do drugiego okna i z powrotem.
Zacznijmy od edytora
„Czy zapisać zmiany?”
Gdy zamykasz dokument z niezapisanymi zmianami, pojawia się okno z pytaniem. Dopóki nie odpowiesz, nie możesz kliknąć niczego innego w programie. To okno modalne.
Panel „Znajdź i zamień” w wielu edytorach zachowuje się inaczej: możesz przełączać się między nim a dokumentem, nie zamykając go. To okno niemodalne.
Znajomość tej różnicy to jedno z najczęściej sprawdzanych zagadnień w zadaniach egzaminacyjnych z aplikacją wielookienkową.
1 · Poznaj narzędzia
Okno modalne, niemodalne i MessageBox
Okno modalneShowDialog()
Blokuje resztę aplikacji, dopóki go nie zamkniesz. Program czeka w linii z ShowDialog() i wraca do niej dopiero po zamknięciu okna.
Na przykład formularz edycji rekordu
Okno niemodalneShow()
Oba okna działają niezależnie. Program nie czeka, wykonanie leci dalej natychmiast.
Na przykład panel narzędzi, okno pomocy
MessageBoxgotowy komunikat
Wbudowane okno modalne do prostych komunikatów i pytań. Nie projektujesz go sam, a wynik sprawdzasz przez MessageBoxResult.
Na przykład „Czy na pewno usunąć?”
Laboratorium · ćwiczenie w przeglądarce, do którego odsyłają rozgrzewki na końcu lekcji
2 · Sprawdź w działaniu
Kiedy program czeka, a kiedy leci dalej
Kliknij „Edytuj” i zobacz, że okno główne się blokuje. Zmień imię i kliknij Zapisz. Potem przełącz sposób otwarcia na Show() i powtórz: tym razem okno główne działa, ale nowe imię się nie pojawia. Wypróbuj też „Usuń” i „Pomoc”.
Jeśli potrzebujesz wyniku z okna (zapisano czy anulowano, co wpisano), użyj ShowDialog(). Show() nie zaczeka na użytkownika.
3 · Kod okna głównego
MainWindow.xaml.cs
Trzy przyciski, trzy techniki. Zauważ, kiedy odczytujesz dane z okna: tylko po ShowDialog().
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, aż użytkownik zamknie okno
if (wynik == true) // użytkownik kliknął „Zapisz”
{
EtykietaImie.Text = okno.ImieDoEdycji; // odczyt danych PO zamknięciu
}
}
private void PrzyciskUsun_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult wynik = MessageBox.Show(
"Czy na pewno chcesz usunąć ten rekord?",
"Potwierdzenie",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
if (wynik == MessageBoxResult.Yes)
{
EtykietaImie.Text = "(usunięto)";
}
}
private void PrzyciskPomoc_Click(object sender, RoutedEventArgs e)
{
OknoPomocy okno = new OknoPomocy();
okno.Show(); // niemodalne: można dalej używać okna głównego
}
}
okno.ImieDoEdycji = EtykietaImie.TextPrzekazanie danych do okna przed jego pokazaniem.bool? wynik = okno.ShowDialog()Program czeka tutaj. Wynik totrue,falsealbonull.if (wynik == true)Zapis tylko wtedy, gdy użytkownik zatwierdził okno przyciskiem Zapisz.MessageBox.Show(…, YesNo, Warning)Pytanie z dwoma przyciskami i ikoną ostrzeżenia. ZwracaMessageBoxResult.okno.Show()Okno pomocy działa równolegle z głównym.
4 · Kod drugiego okna
OknoEdycji.xaml.cs
Okno dialogowe udostępnia publiczną właściwość, przez którą wymienia dane z oknem głównym, i ustawia DialogResult.
using System.Windows;
namespace OknaApp;
public partial class OknoEdycji : Window
{
public string ImieDoEdycji
{
get => PoleImie.Text;
set => PoleImie.Text = value;
}
public OknoEdycji()
{
InitializeComponent();
}
private void Zapisz_Click(object sender, RoutedEventArgs e)
{
DialogResult = true; // zamyka okno i zwraca true do ShowDialog()
}
}
public string ImieDoEdycjiMost do danych: okno główne ustawia ją przed pokazaniem i odczytuje po zamknięciu.DialogResult = trueZamyka okno i zwracatruedoShowDialog().IsCancel="True"na przycisku Anuluj W XAML ten atrybut sam zamyka okno z wynikiemfalse, więc przycisk nie potrzebuje kodu.IsDefault="True"na Zapisz reaguje na Enter.
Do zadań
Lista, błąd bez zamykania okna i okno statystyk
Zadania 2 i 3 wymagają trzech rzeczy: dodania wpisu do ListBox, zostawienia okna otwartego po błędzie oraz odświeżania drugiego okna. Najprościej przekazać drugiemu oknu tę samą kolekcję przez konstruktor.
// --- Okno dodawania: błędna cena nie zamyka okna ---
private void Zapisz_Click(object sender, RoutedEventArgs e)
{
if (!double.TryParse(PoleCena.Text, out double cena))
{
MessageBox.Show("Cena musi być liczbą.", "Błąd", MessageBoxButton.OK, MessageBoxImage.Warning);
return; // wychodzimy, DialogResult nie zostaje ustawiony
}
Nazwa = PoleNazwa.Text;
Cena = cena;
DialogResult = true; // dopiero to zamyka okno
}
// --- Okno główne: dopisanie wpisu do ListBox ---
Lista.Items.Add($"{okno.Nazwa} – {okno.Cena:0.00} zł");
// --- Okno główne: statystyki dostają tę samą kolekcję ---
private readonly ObservableCollection<string> zadania = new(); // using System.Collections.ObjectModel;
new StatystykiWindow(zadania).Show(); // Show() = niemodalne
// --- StatystykiWindow ---
public StatystykiWindow(ObservableCollection<string> lista)
{
InitializeComponent();
void Odswiez() => EtykietaLiczba.Text = $"Liczba zadań: {lista.Count}";
Odswiez();
lista.CollectionChanged += (s, e) => Odswiez(); // wersja ze zdarzeniem
}
double.TryParsePróbuje zamienić tekst na liczbę i zwracatruealbofalse. Wynik trafia do zmiennej po słowieout.CollectionChangedZdarzenieObservableCollection: odpala się po każdym dodaniu i usunięciu elementu, więc okno statystyk odświeża się samo.- Zamiast zdarzenia Możesz też użyć
DispatcherTimerz lekcji o kontrolkach: wTickustaw etykietę nalista.Count.
5 · Komunikaty
Przyciski i wyniki MessageBox
| `MessageBoxButton` | Przyciski | Możliwe wyniki `MessageBoxResult` |
|---|---|---|
OK | OK | OK |
OKCancel | OK, Anuluj | OK, Cancel |
YesNo | Tak, Nie | Yes, No |
YesNoCancel | Tak, Nie, Anuluj | Yes, No, Cancel |
6 · Czego unikać
Trzy pułapki z oknami
`Show()` tam, gdzie potrzebny jest wynik
okno.Show();
EtykietaImie.Text = okno.ImieDoEdycji; // odczyt od razuOdczytujesz starą wartość, bo program nie zaczekał na użytkownika.
if (okno.ShowDialog() == true)
{
EtykietaImie.Text = okno.ImieDoEdycji;
}Tylko ShowDialog() zatrzymuje wykonanie do zamknięcia okna.
Brak `DialogResult` w oknie dialogowym
private void Zapisz_Click(object sender, RoutedEventArgs e)
{
Close(); // bez DialogResult
}ShowDialog() zwraca false (albo null), więc okno główne nie zapisze zmian.
private void Zapisz_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
}Wynik true odróżnia „Zapisz” od „Anuluj” i zamknięcia krzyżykiem.
Wielokrotne otwarcie tego samego okna niemodalnego
private void PrzyciskPomoc_Click(object sender, RoutedEventArgs e)
{
new OknoPomocy().Show();
}Każde kliknięcie otwiera kolejne okno pomocy.
private OknoPomocy? _pomoc;
private void PrzyciskPomoc_Click(object sender, RoutedEventArgs e)
{
if (_pomoc == null || !_pomoc.IsLoaded)
_pomoc = new OknoPomocy();
_pomoc.Show();
_pomoc.Activate();
}Zapamiętaj okno w polu klasy i otwórz je ponownie tylko wtedy, gdy zostało zamknięte.
7 · Sprawdź się
Show, ShowDialog czy MessageBox?
Cztery sytuacje z oknami.
Podsumowanie
Co warto zapamiętać
- Modalne (
ShowDialog()): blokuje resztę, program czeka i dostaje wynik (bool?). - Niemodalne (
Show()): oba okna działają, program leci dalej. - Dane przekazujesz przez publiczną właściwość okna: ustaw przed pokazaniem, odczytaj po
ShowDialog(). DialogResult = truezamyka okno i zwracatrue.IsCancelzamyka z wynikiemfalse.- MessageBox to gotowe okno modalne, a wynik porównujesz z
MessageBoxResult.
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ę →