Aplikacje mobilne · Nawigacja

Nawigacja I: NavigationPage i okna modalne

Rzadko aplikacja mobilna ma jeden ekran. Są ekrany logowania, listy, szczegółów, ustawień, a nawigacja to mechanizm przechodzenia między nimi. Poznasz dwa klasyczne sposoby: stos stron (NavigationPage) i okna modalne, oraz dwa sposoby przekazywania danych między stronami.

  • około 55 minut
  • .NET MAUI · NavigationPage · PushAsync · PushModalAsync
  • INF.04.6.2

Po tej lekcji: przejść do nowej strony i wrócić (PushAsync/PopAsync), otworzyć okno modalne (PushModalAsync/PopModalAsync) oraz przekazać dane przez konstruktor i przez właściwość.

Dwa sposoby przejścia i powrotu z danymi

Wizytówka, szczegóły produktu czy formularz: aplikacje mają więcej niż jeden ekran. Zbudujesz stos stron i osobny ekran modalny, a imię przejdzie razem z nawigacją.

Najpierw uruchomisz mały ekran. Potem połączysz go z kodem i sprawdzisz konkretne wyniki. Dodatki wykonuj dopiero, gdy wersja podstawowa działa. Quiz i oceniane zadania pozostają w biurku po zalogowaniu.

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

1 · Sprawdź w działaniu

Zobacz, co dzieje się na stosie

Wpisz imię i kliknij PushAsync: na stosie pojawi się SecondPage, a w pasku strzałka wstecz. Otwórz okno modalne i zauważ, że nie ma przycisku wstecz. Odznacz opcję NavigationPage i spróbuj PushAsync, aby zobaczyć błąd.

Najpierw przewidź, potem sprawdź: Dodaj stronę na stos, potem wróć. Porównaj to z otwarciem modala. Odpowiedz, czy PopAsync i PopModalAsync zdejmują tę samą warstwę.

Ta interakcja wymaga włączonego JavaScriptu.

Push/Pop działają na stosie stron. Okno modalne jest osobnym stosem i wymaga jawnego zamknięcia. Model pomaga zobaczyć mechanizm; właściwą aplikację uruchomisz z plików poniżej.

1. Przygotuj miejsce pracy

Co dodajesz, a co podmieniasz?

Stronę dodaj przez Projekt → Dodaj → Nowy element → .NET MAUI ContentPage (XAML). Powstaje para .xaml i .xaml.cs. Dla ContentView wybierz szablon ContentView; dla modeli i serwisów zwykłą klasę. Jeśli plik już istnieje, podmień wskazaną zawartość — nie twórz drugiej klasy o tej samej nazwie.

PlikRola w ćwiczeniu
App.xaml.csLogika i obsługa danych
MainPage.xaml.csLogika i obsługa danych
SecondPage.xaml.csLogika i obsługa danych
ThirdPage.xaml.csLogika i obsługa danych
MainPage.xamlWygląd strony lub kontrolki
SecondPage.xamlWygląd strony lub kontrolki
ThirdPage.xamlWygląd strony lub kontrolki

Zanim uruchomisz: trzy połączenia

x:Class="MojaAplikacja.NazwaStrony" w XAML musi zgadzać się z namespace MojaAplikacja i nazwą klasy C#. InitializeComponent() tworzy kontrolki opisane w XAML.

x:Name="PoleImie" daje kodowi C# dostęp przez PoleImie.Text. Z kolei Clicked="Zapisz_Clicked" wskazuje metodę o tej nazwie w pliku .xaml.cs. Sam napis przycisku w Text niczego nie podpina.

Gdy dodajesz XAML z obsługą zdarzeń, od razu uzupełnij też odpowiadający C#. Uruchamiaj dopiero po skończeniu oznaczonej pary plików; brakujący handler nie jest błędem środowiska.

2. Uruchom sam wygląd — jeszcze bez logiki

W świeżym projekcie zastąp MainPage.xaml poniższym ekranem. W MainPage.xaml.cs zachowaj konstruktor z InitializeComponent(); usuń szablonowy licznik i OnCounterClicked, bo nie ma ich już w XAML. Na tym etapie App i AppShell pozostają z szablonu. To pełny, tymczasowy XAML — później świadomie go podmienisz, nie dokleisz do drugiego ContentPage.

MainPage.xaml — etap tymczasowyxaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MojaAplikacja.MainPage">
    <VerticalStackLayout Padding="24" Spacing="14">
        <Label Text="Pierwszy ekran" FontSize="24" />
        <Entry Placeholder="Imię do przekazania" />
        <Button Text="Drugi ekran — za chwilę" />
    </VerticalStackLayout>
</ContentPage>
  1. Pierwsza próba Uruchom. Zobaczysz kontrolki, ale przyciski bez Clicked jeszcze nic nie robią. Sprawdź rozmiar i kolejność elementów. Zatrzymaj aplikację przed następnym etapem.

Zacznijmy od kontaktów

Stos kartek i okno na wierzchu

Przejście z listy produktów do szczegółów produktu i powrót to stos stron: PushAsync dokłada kartkę na wierzch, PopAsync ją zdejmuje. Formularz „Dodaj nowy kontakt”, który otwiera się na wierzchu listy i trzeba go świadomie zamknąć, to nawigacja modalna.

2 · Ściągawka

Push, Pop i modal

MetodaDziałanie
await Navigation.PushAsync(new DrugaStrona())Przechodzi do nowej strony: dokłada ją na stos.
await Navigation.PopAsync()Wraca do poprzedniej strony: zdejmuje bieżącą ze stosu.
await Navigation.PopToRootAsync()Zdejmuje wszystkie strony, zostaje główna.
await Navigation.PushModalAsync(new Strona())Otwiera stronę jako modalne okno „na wierzchu”.
await Navigation.PopModalAsync()Zamyka okno modalne.
Wszystkie metody są asynchroniczne, więc poprzedź je `await` w metodzie oznaczonej `async`.

4. Połącz wygląd z działaniem

Teraz zbuduj docelowy przykład. Pełne pliki poniżej zastępują swoje wcześniejsze wersje. Przeczytaj opis nad kodem i objaśnienia pod nim; potem sprawdź przepływ danych, nie tylko brak czerwonych podkreśleń.

Gdy przykład ma kilka plików zależnych od siebie, najpierw dodaj wszystkie wskazane typy, a potem uruchom całość. Ustaw breakpoint w obsłudze głównego przycisku i prześledź jedną próbę.

Budowa krok po kroku

App.xaml.cs: okno z NavigationPage

Po utworzeniu stron podmień App.xaml.cs. NavigationPage musi być korzeniem okna, żeby stosowe PushAsync i PopAsync miały właściwy kontekst.

Aby PushAsync i PopAsync działały, aplikacja musi zaczynać od NavigationPage.

App.xaml.cscsharp
namespace MojaAplikacja;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
    }

    // Okno aplikacji zawiera NavigationPage, dzięki czemu działają PushAsync i PopAsync
    protected override Window CreateWindow(IActivationState? activationState)
    {
        return new Window(new NavigationPage(new MainPage()));
    }
}
  1. new Window(new NavigationPage(new MainPage())) Stos nawigacji startuje od MainPage. Strony pokazują pasek z tytułem i strzałką wstecz.
  2. CreateWindow W nowszych wersjach MAUI okno tworzysz w tej metodzie. W starszych materiałach zobaczysz MainPage = new NavigationPage(new MainPage());.

Budowa krok po kroku

Widok MainPage

Dodaj lub otwórz MainPage.xaml i podmień jego zawartość. Najpierw odszukaj kontener, potem nazwane kontrolki oraz wskazane zdarzenia. Pozostaw zgodne x:Class i nazwę klasy w pliku .xaml.cs.

Dodaj stronę szablonem ContentPage (XAML), a następnie dopasuj XAML i omówiony wyżej code-behind. Nie wystarczy utworzyć pustej klasy C#.

MainPage.xamlxaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MojaAplikacja.MainPage">
    <VerticalStackLayout Padding="20" Spacing="12">
        <Entry x:Name="PoleImie" Placeholder="Imię" />
        <Button Text="Druga strona" Clicked="OnGoClicked" />
        <Button Text="Strona modalna" Clicked="OnModalClicked" />
    </VerticalStackLayout>
</ContentPage>
  1. Przeczytaj powiązanie x:Name identyfikuje kontrolkę, a Binding odczytuje właściwość obiektu ustawionego jako BindingContext. To dwa różne mechanizmy.

Budowa krok po kroku

MainPage.xaml.cs

Odczytaj imię przed przejściem. SecondPage dostaje argument konstruktora; ThirdPage właściwość ustawioną przed PushModalAsync.

Dwa przyciski: zwykłe przejście z przekazaniem imienia oraz okno modalne.

MainPage.xaml.cscsharp
namespace MojaAplikacja;

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));
    }

    private async void OnModalClicked(object sender, EventArgs e)
    {
        var trzecia = new ThirdPage { Imie = PoleImie.Text ?? "" };
        await Navigation.PushModalAsync(trzecia);   // okno modalne: bez przycisku „wstecz”
    }
}
  1. PoleImie.Text ?? "" Zamienia null na pusty napis, aby nie przekazać pustego odwołania.
  2. new SecondPage(imie) Dane przekazane przez konstruktor nowej strony, w chwili jej tworzenia.
  3. PushModalAsync(trzecia) Otwiera stronę jako okno modalne.

Budowa krok po kroku

Widok SecondPage

Dodaj lub otwórz SecondPage.xaml i podmień jego zawartość. Najpierw odszukaj kontener, potem nazwane kontrolki oraz wskazane zdarzenia. Pozostaw zgodne x:Class i nazwę klasy w pliku .xaml.cs.

Dodaj stronę szablonem ContentPage (XAML), a następnie dopasuj XAML i omówiony wyżej code-behind. Nie wystarczy utworzyć pustej klasy C#.

SecondPage.xamlxaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MojaAplikacja.SecondPage">
    <VerticalStackLayout Padding="20" Spacing="12">
        <Label x:Name="LabelImie" />
        <Button Text="Wróć" Clicked="OnBackClicked" />
    </VerticalStackLayout>
</ContentPage>
  1. Przeczytaj powiązanie x:Name identyfikuje kontrolkę, a Binding odczytuje właściwość obiektu ustawionego jako BindingContext. To dwa różne mechanizmy.

Budowa krok po kroku

SecondPage.xaml.cs

Konstruktor nie jest tu bezargumentowy. new SecondPage(imie) musi przekazać wartość; po InitializeComponent ustawiamy etykietę.

Druga strona odbiera imię jako parametr konstruktora i od razu pokazuje powitanie. MAUI sam pamięta, skąd użytkownik przyszedł.

SecondPage.xaml.cscsharp
namespace MojaAplikacja;

public partial class SecondPage : ContentPage
{
    public SecondPage(string imie)
    {
        InitializeComponent();
        LabelImie.Text = $"Witaj, {imie}!";
    }

    private async void OnBackClicked(object sender, EventArgs e)
    {
        // Powrót do poprzedniej strony (zdejmuje SecondPage ze stosu)
        await Navigation.PopAsync();
    }
}
  1. public SecondPage(string imie) Konstruktor z parametrem: dane dostajesz w chwili tworzenia strony.
  2. InitializeComponent() przed użyciem kontrolek Najpierw tworzymy kontrolki, dopiero potem ustawiamy LabelImie.Text.
  3. await Navigation.PopAsync() Zdejmuje stronę ze stosu i wraca do poprzedniej.

Budowa krok po kroku

Widok ThirdPage

Dodaj lub otwórz ThirdPage.xaml i podmień jego zawartość. Najpierw odszukaj kontener, potem nazwane kontrolki oraz wskazane zdarzenia. Pozostaw zgodne x:Class i nazwę klasy w pliku .xaml.cs.

Dodaj stronę szablonem ContentPage (XAML), a następnie dopasuj XAML i omówiony wyżej code-behind. Nie wystarczy utworzyć pustej klasy C#.

ThirdPage.xamlxaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MojaAplikacja.ThirdPage">
    <VerticalStackLayout Padding="20" Spacing="12">
        <Label x:Name="EtykietaWiadomosc" />
        <Button Text="Zamknij" Clicked="OnZamknijClicked" />
    </VerticalStackLayout>
</ContentPage>
  1. Przeczytaj powiązanie x:Name identyfikuje kontrolkę, a Binding odczytuje właściwość obiektu ustawionego jako BindingContext. To dwa różne mechanizmy.

Budowa krok po kroku

ThirdPage.xaml.cs

Modal ma własny sposób zamknięcia PopModalAsync. Porównaj go z PopAsync na zwykłym stosie.

Dane można też przekazać przez właściwość: tworzysz stronę, ustawiasz właściwość i dopiero wtedy ją pokazujesz. Odczyt robisz w OnAppearing().

ThirdPage.xaml.cscsharp
namespace MojaAplikacja;

public partial class ThirdPage : ContentPage
{
    // Dane przekazane PRZEZ WŁAŚCIWOŚĆ: ustawiamy je PRZED PushAsync
    public string Imie { get; set; } = "";

    public ThirdPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        EtykietaWiadomosc.Text = $"Cześć, {Imie}!";   // odczyt po pojawieniu się strony
    }

    private async void OnZamknijClicked(object sender, EventArgs e)
    {
        await Navigation.PopModalAsync();
    }
}
  1. public string Imie { get; set; } Publiczna właściwość, którą ustawi strona wywołująca.
  2. OnAppearing() Uruchamia się, gdy strona staje się widoczna, więc właściwość jest już ustawiona.
  3. await Navigation.PopModalAsync() Okno modalne zamykamy jawnie (nie ma przycisku wstecz).

5. Odbiór: czy naprawdę działa?

Wykonaj próby w swojej aplikacji, nie tylko w modelu na stronie. Zaznaczaj dopiero po sprawdzeniu wyniku. Funkcje urządzenia wymagają testu na właściwej platformie.

7 · Czego unikać

Cztery błędy w nawigacji

Brak `NavigationPage`
Tak nie
return new Window(new MainPage());

Navigation.PushAsync zgłasza wyjątek, bo strona nie ma stosu nawigacji.

Tak
return new Window(new NavigationPage(new MainPage()));

Stos stron istnieje tylko w NavigationPage.

Mylenie `PushAsync` z `PushModalAsync`
Tak nie
await Navigation.PushModalAsync(new SzczegolyPage());   // zwykłe szczegóły

Brak przycisku „wstecz”, a użytkownik musi zamknąć okno jawnie.

Tak
await Navigation.PushAsync(new SzczegolyPage());

Modal jest do formularzy i potwierdzeń, a zwykłe przejścia do PushAsync.

Właściwość ustawiona po pokazaniu strony
Tak nie
await Navigation.PushAsync(trzecia);
trzecia.Imie = "Ola";

OnAppearing() wykonało się z pustym Imie.

Tak
trzecia.Imie = "Ola";
await Navigation.PushAsync(trzecia);

Dane muszą być gotowe, zanim strona stanie się widoczna.

Brak `await` przed nawigacją
Tak nie
Navigation.PushAsync(new SecondPage(imie));

Kod idzie dalej, nie czekając na przejście. Możliwe nieprzewidywalne zachowanie animacji.

Tak
await Navigation.PushAsync(new SecondPage(imie));

Metody nawigacji są asynchroniczne.

Ćwiczenie z pomocą · samodzielna praca

6. Mała zmiana, którą zrobisz samodzielnie

Przekaż do SecondPage także nazwę klasy ucznia.

Oczekiwany rezultat
Przekaż do SecondPage także nazwę klasy ucznia.
Dotychczasowe działanie ma pozostać poprawne.
Potrzebujesz pomocy? Rozwiązuj krok po kroku.
Krok 1 — pokaż podpowiedź

Dodaj drugi Entry na MainPage.

Krok 2 — pokaż podpowiedź

Rozszerz konstruktor SecondPage o drugi argument typu string.

Krok 3 — pokaż podpowiedź

Uzupełnij zarówno wywołanie new SecondPage(...), jak i tekst wyświetlany w konstruktorze.

Otwórz tylko tyle podpowiedzi, ile potrzebujesz. Po każdym kroku wróć do zadania i sprawdź wynik.

8 · Sprawdź się

Którą metodę nawigacji?

Cztery sytuacje.

Ta interakcja wymaga włączonego JavaScriptu.

Podsumowanie

Co warto zapamiętać

  1. NavigationPage tworzy stos stron: PushAsync dokłada, PopAsync zdejmuje, PopToRootAsync wraca do głównej.
  2. Okno modalne: PushModalAsync i PopModalAsync, bez przycisku wstecz.
  3. Dane przekaż przez konstruktor albo przez **właściwość ustawioną przed PushAsync** (odczyt w OnAppearing()).
  4. Metody nawigacji są asynchroniczne: używaj await w metodzie async.
  5. Bez NavigationPage w CreateWindow metody Push/Pop zgłoszą wyjątek.

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