.NET MAUI - XAML stack navigation

2022. 7. 22. 00:00MAUI

반응형

Statack Navigation

: 이동한 페이지가  이전 페이지에서 선택한 항목에 대한 더 자세한 보기를 제공하는 형태

 

Shall class는 다음과 같은 탐색 관련 속성을 정의한다. 

  • BackButtonBehavior
    : 뒤로 가는 버튼에 대한 동작을 정의 하는 속성
  • CurrentItem 
    : 현재 선택된 Item (ShellItem Type)
  • CurrentPage
    :  현재 표시된 페이지 (Page Type)
  • CurrentState
    : Shell 의 현재 탐색 상태 (ShellNavigationState Type)
  • Current
    :  Application.Current.MainPage 에 대한 type-casted 별칭

탐색은 Shell class 에서  GoToAsync 메서드를 호출하여 수행된다. 

 

Route

라우트는 아래와 같은 형태로 구성된다. 

//route/page?queryParameters

 

Route

: Shell 시각적 계층 구조의 일부로 존재하는 콘텐츠에 대한 경로를 정의

 

Page

: Shell 시각적 계층 구조에서 정의되지 않지만 필요에 따라 Navigation statck 에 push 가능 하다.

 

Parameters

: 페이지 이동시 대상 페이지로 전달할 수 있는 매개변수

 

경로등록 (Register routes)

Route 속성을 통해 FlyoutItem, TabBar, Tab 및 ShellContent 에 경로를 정의할 수 있다. 

<Shell ...>
    <FlyoutItem ... 
        Route = "astronomy">
        <ShellContent ...
            Route="moonphase" />
        <ShellContent ...
            Route="sunrise" />
    </FlyoutItem>
    <FlyoutItem>
        <ShellContent ...
            Route="about" />
    </FlyoutItem>
</Shell>

moonphase 로 이동하려면 astronomy/moonphase 로 이동해야 한다. 

 

상세 경로 등록 (Register detail routes)

Routing.RegisterRoute("astronomicalbodydetails", typeof(AstronomicalBodyPage));

해당 경로로 이동하려면 다음을 호출 한다.

await Shell.Current.GoToAsync("..");

Data 를 전달 하려면 다음과 같이 한다. 

string celestialName = "moon";

await Shell.Current.GoToAsync($"astronomicalbodydetails?bodyName={celestialName}");

 

Data 를 가져 오려면 다음과 같이 한다. (QueryProperty 를 이용하여 bodyName 에 값을 AstroName 에 매핑한다.

[QueryProperty(nameof(AstroName), "bodyName")]
public partial class AstronomicalBodyPage : ContentPage
{
    string astroName;
    public string AstroName
    {
        get => astroName;
        set
        {
            astroName = value;
        }
    }

    ...
}

 

예제) 아래와 같이 root --> detail 형태의 탐색을 구현 한다고 하자

 

이전 강좌에서 사용했던 예제에 몇가지 파일을 추가하자

AstronomicalBodiesPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackNavigation.Pages.AstronomicalBodiesPage"
             Title="Astronomical Bodies">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Button">
                <Setter Property="FontSize" Value="100" />
                <Setter Property="BorderColor" Value="DarkGray" />
            </Style>
            <Style TargetType="Label">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="End" />
                <Setter Property="Margin" Value="5" />
                <Setter Property="FontAttributes" Value="Bold" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <Grid Margin="8">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button x:Name="btnEarth" Grid.Row="0" Grid.Column="0" Text="🌎" />
        <Button x:Name="btnMoon"  Grid.Row="0" Grid.Column="1" Text="🌕" />
        <Button x:Name="btnSun"   Grid.Row="1" Grid.Column="0" Text="☀️" />
        <Button x:Name="btnComet" Grid.Row="1" Grid.Column="1" Text="☄" />
    </Grid>
</ContentPage>

AstronomicalBodyPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackNavigation.Pages.AstronomicalBodyPage"
             Title="Astronomical Body">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Color x:Key="textColor">White</Color>
            <Style TargetType="Label">
                <Setter Property="TextColor" Value="{StaticResource textColor}" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <Shell.BackButtonBehavior>
        <BackButtonBehavior IconOverride="comet.png"/>
    </Shell.BackButtonBehavior>

    <Grid RowSpacing="10" ColumnSpacing="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Image Aspect="AspectFill" Grid.RowSpan="6" Grid.ColumnSpan="2" Source="starfield.png" />

        <Label x:Name="lblIcon" FontSize="96" Grid.Row="0" Grid.ColumnSpan="2" HorizontalOptions="Center" />
        <Label x:Name="lblName" FontSize="Medium" FontAttributes="Bold" Grid.Row="1" Grid.ColumnSpan="2" HorizontalOptions="Center" />

        <Label FontSize="Medium" FontAttributes="Bold" Grid.Row="2" HorizontalOptions="End" Text="Mass:" />
        <Label FontSize="Medium" FontAttributes="Bold" Grid.Row="3" HorizontalOptions="End" Text="Circumference:" />
        <Label FontSize="Medium" FontAttributes="Bold" Grid.Row="4" HorizontalOptions="End" Text="Age:" />

        <Label x:Name="lblMass" FontSize="Medium" Grid.Row="2" Grid.Column="1" />
        <Label x:Name="lblCircumference" FontSize="Medium" Grid.Row="3" Grid.Column="1" />
        <Label x:Name="lblAge" FontSize="Medium" Grid.Row="4" Grid.Column="1" />
    </Grid>
</ContentPage>

AstronomicalBodyPage.xaml.cs

using MauiApp1.Xaml.StackNavigation.Data;

namespace MauiApp1.Xaml.StackNavigation.Pages;

public partial class AstronomicalBodyPage : ContentPage
{
    public AstronomicalBodyPage()
    {
        InitializeComponent();
    }
    void UpdateAstroBodyUI(string astroName)
    {
        AstronomicalBody body = FindAstroData(astroName);

        Title = body.Name;

        lblIcon.Text = body.EmojiIcon;
        lblName.Text = body.Name;
        lblMass.Text = body.Mass;
        lblCircumference.Text = body.Circumference;
        lblAge.Text = body.Age;
    }

    AstronomicalBody FindAstroData(string astronomicalBodyName)
    {
        return astronomicalBodyName switch
        {
            "comet" => SolarSystemData.HalleysComet,
            "earth" => SolarSystemData.Earth,
            "moon" => SolarSystemData.Moon,
            "sun" => SolarSystemData.Sun,
            _ => throw new ArgumentException()
        };
    }
}

Data/AstronomicalBody.cs

namespace MauiApp1.Xaml.StackNavigation.Data;
public class AstronomicalBody
{
    public string Name { get; set; }
    public string Mass { get; set; }
    public string Circumference { get; set; }
    public string Age { get; set; }
    public string EmojiIcon { get; set; }
}

Data/SolarSystemData.cs

namespace MauiApp1.Xaml.StackNavigation.Data;
public static class SolarSystemData
{
    public static AstronomicalBody Sun = new AstronomicalBody()
    {
        Name = "The Sun (Sol)",
        Mass = "1.9855*10^30 kg",
        Circumference = "4,379,000 km",
        Age = "4.57 billion years",
        EmojiIcon = "☀️",
    };

    public static AstronomicalBody Earth = new AstronomicalBody()
    {
        Name = "Earth",
        Mass = "5.97237*10^24 kg",
        Circumference = "40,075 km",
        Age = "4.54 billion years",
        EmojiIcon = "🌎",
    };

    public static AstronomicalBody Moon = new AstronomicalBody()
    {
        Name = "Moon",
        Mass = "7.342*10^22 kg",
        Circumference = "10,921 km",
        Age = "4.53 billion years",
        EmojiIcon = "🌕",
    };

    public static AstronomicalBody HalleysComet = new AstronomicalBody()
    {
        Name = "Halley's Comet",
        Mass = "22 * 10^14 kg",
        Circumference = "11 km",
        Age = "4.6 billion years",
        EmojiIcon = "☄",
    };
}

Resources 는 asset 을 참고하여 추가하자

 

 

이제 상세 페이지를 위해  AppShell  class 에 경로(route)를 추가하자

public AppShell()
{
    InitializeComponent();

    Routing.RegisterRoute("astronomicalbodydetails", typeof(AstronomicalBodyPage));
}

 AstronomicalBodiesPage.xaml.cs

public AstronomicalBodiesPage()
{
    InitializeComponent();

    btnComet.Clicked += async (s, e) => await Shell.Current.GoToAsync("astronomicalbodydetails?astroName=comet");
    btnEarth.Clicked += async (s, e) => await Shell.Current.GoToAsync("astronomicalbodydetails?astroName=earth");
    btnMoon.Clicked += async (s, e) => await Shell.Current.GoToAsync("astronomicalbodydetails?astroName=moon");
    btnSun.Clicked += async (s, e) => await Shell.Current.GoToAsync("astronomicalbodydetails?astroName=sun");
}

 AstronomicalBodyPage.xaml.cs

string astroName;
public string AstroName
{
    get => astroName;
    set
    {
        astroName = value;

        // this is a custom function to update the UI immediately
        UpdateAstroBodyUI(astroName);
    } 
}
[QueryProperty(nameof(AstroName), "astroName")]
public partial class AstronomicalBodyPage
{ ...

git source 참조

 

 

관련영상

https://youtu.be/oQq9xz54owY

 

반응형

'MAUI' 카테고리의 다른 글

.NET MAUI - Binding 모드  (0) 2022.07.26
.NET MAUI - Binding 기본  (0) 2022.07.25
NET MAUI - XAML tab navigation  (0) 2022.07.21
NET MAUI - XAML flyout navigation  (0) 2022.07.20
NET MAUI - XAML 애플리케이션 전체 리소스 생성 및 사용  (0) 2022.07.19