Lekcja 11. Nawigacja I — NavigationPage i nawigacja modalna
Trudny / egzaminacyjnyPo co się tego uczymy?
Rzadko aplikacja mobilna ma tylko jeden ekran — zwykle są ekrany logowania, listy, szczegółów, ustawień. Nawigacja to mechanizm przechodzenia między nimi. Ta lekcja pokazuje dwa klasyczne sposoby: NavigationPage (stos stron, "przejdź dalej/wróć") i nawigację modalną (pełnoekranowe okno na wierzchu). Trzeci, nowoczesny sposób — Shell — poznasz w kolejnej lekcji.
Teoria
NavigationPage — stos stron
Działa jak stos kartek: PushAsync() dokłada nową kartkę (nową stronę) na wierzch, PopAsync() zdejmuje ją, wracając do poprzedniej. To najprostszy sposób realizacji klasycznego "przejdź dalej / wróć", np. lista uczniów → szczegóły ucznia.
| Metoda | Działanie |
|---|---|
await Navigation.PushAsync(new DrugaStrona()) |
Przejście do nowej strony (dokłada ją na stos). |
await Navigation.PopAsync() |
Powrót do poprzedniej strony (zdejmuje bieżącą ze stosu). |
Żeby NavigationPage działał, trzeba go ustawić jako główną stronę aplikacji w App.xaml.cs: MainPage = new NavigationPage(new MainPage());
Nawigacja modalna — okno na wierzchu
To jak otwarcie pełnoekranowego okna dialogowego — dopóki go nie zamkniesz, nie wrócisz do poprzedniej strony. Typowe zastosowanie: formularze, logowanie, potwierdzenia, okna wyboru.
| Metoda | Działanie |
|---|---|
await Navigation.PushModalAsync(new Strona()) |
Otwiera stronę jako modalne okno "na wierzchu". |
await Navigation.PopModalAsync() |
Zamyka modalne okno, wracając do strony pod spodem. |
Przekazywanie danych między stronami — dwa sposoby
Przez konstruktor — dane przekazujesz w momencie TWORZENIA strony: await Navigation.PushAsync(new SecondPage(imie));, a druga strona odbiera je w swoim konstruktorze.
Przez właściwość — najpierw tworzysz stronę, POTEM ustawiasz jej właściwość publiczną, a odczytujesz ją w metodzie OnAppearing() (poznanej w pierwszej lekcji tego działu — uruchamia się dokładnie wtedy, gdy strona staje się widoczna):
var third = new ThirdPage();
third.Imie = _imie; // przekazanie danych przez wlasciwosc, PRZED PushAsync
await Navigation.PushAsync(third);
Oba sposoby są proste i w pełni wystarczające na egzaminie INF.04.
Schemat
Trzy sposoby nawigacji (ten i nastepny wykladany w tej lekcji: dwa pierwsze): NavigationPage (stos kartek): MainPage --PushAsync--> SecondPage --PushAsync--> ThirdPage MainPage <--PopAsync--- SecondPage <--PopAsync--- ThirdPage Modal (okno na wierzchu, blokuje powrot dopoki nie zamkniesz): MainPage --PushModalAsync--> [OKNO MODALNE] --PopModalAsync--> MainPage
Przykład z życia
Formularz "Dodaj nowy kontakt" otwierający się jako pełnoekranowe okno NA WIERZCHU listy kontaktów, które trzeba świadomie zamknąć (przyciskiem "Zapisz" albo "Anuluj") — to klasyczny wzorzec nawigacji modalnej. Z kolei przechodzenie z listy produktów do szczegółów produktu, a potem powrót do listy przez strzałkę "wstecz" — to typowy NavigationPage.
MainPage.xaml
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NawigacjaApp.MainPage">
<VerticalStackLayout Padding="20" Spacing="12">
<Entry x:Name="PoleImie" Placeholder="Podaj imię" />
<Button Text="Przejdź dalej" Clicked="OnGoClicked" />
</VerticalStackLayout>
</ContentPage>
MainPage.xaml.cs + SecondPage.xaml.cs
// MainPage.xaml.cs
namespace NawigacjaApp;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnGoClicked(object sender, EventArgs e)
{
string imie = PoleImie.Text ?? "";
// Przekazanie danych PRZEZ KONSTRUKTOR drugiej strony
await Navigation.PushAsync(new SecondPage(imie));
}
}
// SecondPage.xaml.cs
namespace NawigacjaApp;
public partial class SecondPage : ContentPage
{
public SecondPage(string imie)
{
InitializeComponent();
LabelImie.Text = $"Witaj, {imie}!";
}
private async void OnBackClicked(object sender, EventArgs e)
{
// Powrot do poprzedniej strony (zdejmuje SecondPage ze stosu)
await Navigation.PopAsync();
}
}
Komentarz i wyjaśnienie kodu
Na MainPage użytkownik wpisuje imię, a kliknięcie przycisku wywołuje Navigation.PushAsync(new SecondPage(imie)) — tworzy nową instancję SecondPage, przekazując wpisane imię PROSTO do jej konstruktora, i dokłada tę stronę na "stos" nawigacji.
SecondPage odbiera imię jako parametr konstruktora i od razu wypisuje powitanie w LabelImie. Przycisk "Wróć" wywołuje Navigation.PopAsync(), który zdejmuje SecondPage ze stosu, automatycznie wracając do MainPage — nie trzeba samodzielnie "pamiętać", skąd użytkownik przyszedł, MAUI robi to za nas.
Zwróć uwagę: żeby Navigation.PushAsync/PopAsync w ogóle działały, aplikacja musi być uruchomiona wewnątrz NavigationPage — ustawionego w App.xaml.cs jako MainPage = new NavigationPage(new MainPage());.
Ćwiczenie samodzielne
Utwórz projekt z dwiema stronami (MainPage, SecondPage) i powyższym kodem, pamiętając o ustawieniu NavigationPage w App.xaml.cs. Sprawdź na emulatorze: czy natywny przycisk "wstecz" (albo strzałka w górnym pasku) też poprawnie wraca do MainPage — to jedna z korzyści korzystania z NavigationPage zamiast ręcznego zarządzania stronami.
Zadania do pracy własnej
Dodaj trzecią stronę ThirdPage i przycisk na SecondPage, który otwiera ją MODALNIE (PushModalAsync) zamiast przez zwykły PushAsync. Zaobserwuj różnicę: czy pojawia się przycisk 'wstecz'?
Przekaż z SecondPage do ThirdPage dane PRZEZ WŁAŚCIWOŚĆ (nie przez konstruktor) — utwórz ThirdPage z publiczną właściwością Imie, ustaw ją PRZED wywołaniem PushAsync, a odczytaj w metodzie OnAppearing().
Zbuduj aplikację 'Lista zadań' z trzema stronami: ListaPage (przycisk 'Dodaj zadanie'), DodajZadaniePage (otwierana MODALNIE, z Entry na treść zadania i przyciskami 'Zapisz'/'Anuluj' — Zapisz zamyka modal przez PopModalAsync i przekazuje wpisany tekst z powrotem przez właściwość publiczną odczytaną po PopModalAsync), i SzczegolyZadaniaPage (otwierana zwykłym PushAsync z listy, pokazuje treść zadania i przycisk 'Wróć').
Typowe błędy
Brak NavigationPage w App.xaml.cs — bez tego wywołanie Navigation.PushAsync rzuci wyjątek, bo strona nie ma dostępu do stosu nawigacji.
Mylenie PushAsync z PushModalAsync — obie "otwierają nową stronę", ale modal blokuje dostęp do przycisku "wstecz" i wymaga jawnego zamknięcia przez PopModalAsync — dobór złej metody psuje oczekiwane zachowanie ekranu.
Ustawianie właściwości PO wywołaniu PushAsync zamiast przed — jeśli ustawisz właściwość strony już PO jej wyświetleniu, `OnAppearing()` zdąży się wykonać z pustą wartością.
Zapominanie o await przed Push/PopAsync — te metody są asynchroniczne; pominięcie await może prowadzić do nieprzewidywalnego zachowania animacji przejścia.
Nawiązanie do egzaminu zawodowego
To realizacja INF.04.6.2 w zakresie nawigacji — kluczowego elementu każdej wieloekranowej aplikacji mobilnej. Umiejętność poprawnego przekazania danych między stronami (przez konstruktor lub właściwość) jest częstym elementem zadań egzaminacyjnych.