.NET MAUI Shell에 λŒ€ν•΄

λ“œλ””μ–΄ .NET MAUI의 RC 버전이 λ‚˜μ™”μŠ΅λ‹ˆλ‹€.

이전에도 μžˆμ—ˆλŠ”μ§€λŠ” λͺ¨λ₯΄κ² μœΌλ‚˜, 적어도 μ œκ°€ MAUI λ°œν‘œμ€€λΉ„λ₯Ό ν–ˆμ—ˆλ˜ 1μ›”κΉŒμ§€λŠ” μ—†μ—ˆλ˜ Shellμ΄λΌλŠ” κ°œλ…μ΄ λ“±μž₯ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
이 Shell은 Xamarin에 μ΅μˆ™ν•œ 뢄듀이라면 쑰금 λ‚―μ„  κ°œλ…μΌν…λ° 이 κΈ°λŠ₯이 무엇을 ν•˜λŠ”μ§€μ— λŒ€ν•΄ 잠깐 μ•Œμ•„λ΄…λ‹ˆλ‹€.

이 글은 μ œκ°€ 개인적으둜 μ΄ν•΄ν•œ 것에 λ”°λ₯΄λ―€λ‘œ, 잘λͺ»λœ λ‚΄μš©μ΄ 있으면 자유둭게 ν”Όλ“œλ°± λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

λ¨Όμ € Shell은 MSDN에 μ„€λͺ…이 μžμ„Ένžˆ λ‚˜μ™”μžˆμœΌλ‚˜ 사싀 읽어봐도 κ°œλ…μ΄ 잘 와닿지 μ•ŠμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ 쑰금 생각해보면 ν”„λ‘œκ·Έλž¨μ˜ UI에 ν•΄λ‹Ήν•  수 μžˆλŠ” κ°€μž₯ μ•ˆμͺ½μ„ Shellμ΄λΌλŠ” κ°œλ…μ„ μ μš©ν•˜μ—¬ κ·Έ μœ„μ—μ„œ νŽ˜μ΄μ§€λ₯Ό 자유둭게 이동할 수 μžˆλŠ” 것은 μ•„λ‹κΉŒ ν•©λ‹ˆλ‹€.

일단 기본적인 ꡬ성은 FlyoutItem, TabItem, ShellContent 3κ°€μ§€κ°€ μžˆμŠ΅λ‹ˆλ‹€.
μ•žμ˜ 두 κ°œλŠ” UI ꡬ성 방법을 Flyout 방식이냐 Tab 방식이냐λ₯Ό λ‚˜νƒ€λ‚Ό 뿐이고, 이 쀑 μ‹€μ œ 화면에 ν‘œν˜„ν•˜λŠ” 것은 ShellContentμž…λ‹ˆλ‹€.
(TabItem은 Xamarin의 TabbedPage와 λΉ„μŠ·ν•˜μ§€λ§Œ μ•„λž˜μͺ½μ— λ‚˜μ˜€λŠ” Route λΆ€λΆ„κ³Ό 차이가 μžˆμŠ΅λ‹ˆλ‹€.)

FlyoutItem

<Shell
    x:Class="MyTest.Maui.AppShell"
    ...>

    <FlyoutItem Title="Cats">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:CatsPage}" 
                                    Route="CatsPage"/>
       </Tab>
    </FlyoutItem>

</Shell>

TabItem

<Shell
    x:Class="MyTest.Maui.AppShell"
    ...>

    <TabBar>
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:DogsPage}"
                                    Route="DogsPage" />
       </Tab>
    </TabBar>

</Shell>

ShellContent

<Shell
    x:Class="MyTest.Maui.AppShell"
    ...
    Shell.FlyoutBehavior="Disabled">

    <ShellContent
        Title="Hello, World!"
        ContentTemplate="{DataTemplate local:MyCustomPage}"
        Route="MyCustomPage" />

</Shell>

μ½”λ“œλ‘œ 보면 μ΄λ ‡κ²Œ μƒκ²ΌλŠ”λ° κ°€μš΄λ° μžˆλŠ” <Tab /> νƒœκ·ΈλŠ” μƒλž΅μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.
λ˜ν•œ 이λ₯Ό μ•„λž˜μ™€ 같이 μ„žμ–΄μ„œ μ“Έ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

<Shell
    x:Class="MyTest.Maui.AppShell"
    ...>

    <FlyoutItem Title="Animals" Route="Animals">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:CatsPage}" 
                                    Route="CatsPage"/>
           <ShellContent ContentTemplate="{DataTemplate views:DogsPage}" 
                                    Route="DogsPage"/>
       </Tab>
    </FlyoutItem>

    <ShellContent
        Title="Hello, World!"
        ContentTemplate="{DataTemplate local:MyCustomPage}"
        Route="MyCustomPage" />

</Shell>

μ—¬κΈ°μ„œ 핡심은 Route ν‚€μ›Œλ“œμž…λ‹ˆλ‹€.
RouteλŠ” 루트 νŽ˜μ΄μ§€λ₯Ό μ΄λ™ν•˜λŠ” κ°€μž₯ μ‰¬μš΄ λ°©λ²•μž…λ‹ˆλ‹€.

κΈ°μ‘΄ Xamarinμ—μ„œλŠ” 루트 νŽ˜μ΄μ§€κ°€ μ•„λž˜ μ½”λ“œμ²˜λŸΌ κ³ μ •λ˜μ–΄ μžˆμ–΄ μ‰½κ²Œ λ°”κΏ€ 수 μ—†μ—ˆμŠ΅λ‹ˆλ‹€.

// κΈ°μ‘΄ Xamarin
public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        MainPage = new NavigationPage(new MainPage());
    }
}
// MAUI
public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }
}

κ·ΈλŸ¬λ‚˜ μ—¬κΈ° Shell을 μ΄μš©ν•˜λ©΄ 루트 νŽ˜μ΄μ§€λ₯Ό ꡉμž₯히 μ‰½κ²Œ λ°”κΏ€ 수 μžˆμŠ΅λ‹ˆλ‹€.
μ΄λ•Œ RouteλŠ” κ·Έ κ²½λ‘œκ°€ 되며 이λ₯Ό Uri μ‹μœΌλ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.

예λ₯Όλ“€μ–΄ μœ„ μ˜ˆμ œμ—μ„œλŠ” 계측도가 μ•„λž˜μ™€ 같이 λ©λ‹ˆλ‹€.

Animals
        CatsPage
        DogsPage
MyCustomPage

이λ₯Ό Uri둜 λ°”κΎΈλ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

//Animals
//Animals/CatsPage
//Animals/DogsPage
//MyCustomPage

각 νŽ˜μ΄μ§€μ˜ 이동은 Uriλ₯Ό 톡해 μ΄λ€„μ§‘λ‹ˆλ‹€.
νŽ˜μ΄μ§€μ˜ 이동은 λΉ„ν•˜μΈλ“œ μ½”λ“œμ—μ„œ μ•„λž˜ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.

await (Application.Current.MainView as Shell).Current.GoToAsync("//MyCustomPage");
// λ˜λŠ”
await Shell.Current.GoToAsync("//MyCustomPage");

μœ„μ—μ„œ μ‚¬μš©ν•œ / κΈ°ν˜ΈλŠ” Uri λ‹¨μœ„μ§€λ§Œ 맨 μ•žμ— λΆ™μœΌλ©΄ 기쀀점이 λ‹¬μ•„μ§€λŠ”λ°,
μ΄λŠ” λ¬Έμ„œλ₯Ό 읽어도(μ˜μ–΄λ„ λ§ˆμ°¬κ°€μ§€) 아직 μ •ν™•ν•˜κ²Œ μ΄ν•΄ν•˜μ§€λŠ” λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.
λ‹€λ§Œ μ ˆλŒ€ κ²½λ‘œκ°€ //둜 μ‹œμž‘ν•œλ‹€λŠ” κ²ƒλ§Œ νŒŒμ•…ν–ˆλ„€μš”.

image

이둜써 루트 νŽ˜μ΄μ§€λ₯Ό μ΄λ™ν•œ λ‹€μŒ λ‚΄λΆ€μ—μ„œλŠ” Xamarin처럼 await Navigation.PushAsync(new NextPage())λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
이 경우 μžλ™μœΌλ‘œ NavigationPage ν˜•νƒœλ‘œ νŒλ‹¨ν•˜μ—¬ μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 λ’€λ‘œκ°€κΈ° μ•„μ΄μ½˜μ΄ μžˆλŠ” λ°”κ°€ μƒκΉλ‹ˆλ‹€.

image


마무리

μ •λ¦¬ν•˜μžλ©΄ MAUI에 μƒˆλ‘œ 생긴 Shell은 루트 νŽ˜μ΄μ§€ λ³€κ²½ 및 일반적인 νŽ˜μ΄μ§€ μ΄λ™μœΌλ‘œ μ‚¬μš©ν•  수 있으며 κ²½λ‘œλŠ” Uri ν˜•μ‹μ„ μ‚¬μš©ν•˜κ³  κ·Έ μœ„μΉ˜λŠ” Shell에 μ •μ˜λœ Depthλ₯Ό λ”°λ¦…λ‹ˆλ‹€.
λ¬Όλ‘  κΈ°μ‘΄ Xamarinκ³Ό 같이 νŽ˜μ΄μ§€λ₯Ό μ΄λ™ν•˜λŠ” 것도 κ°€λŠ₯ν•©λ‹ˆλ‹€.
이둜써 μ œκ°€ μ΄ν•΄ν•œ λ°”λ‘œλŠ” 기쑴에 App 클래슀 λ‚΄λΆ€μ˜ MainViewκ°€ κ°•ν•˜κ²Œ μ—°κ²°λ˜μ–΄ 있던 것을 λŠμŠ¨ν•˜κ²Œ κ²°ν•©ν•  수 μžˆλ„λ‘ ν”„λ‘œκ·Έλž˜λ° 적으둜 ν•΄μ†Œν•œ κ²ƒμœΌλ‘œ 보이며, μ΄λŠ” λ‹€μ–‘ν•œ μ‹œλ‚˜λ¦¬μ˜€μ—μ„œ μ‚¬μš©μ΄ κ°€λŠ₯ν•  것 κ°™μŠ΅λ‹ˆλ‹€.

11개의 μ’‹μ•„μš”

λ©‹μ§„ 포슀트 μž…λ‹ˆλ‹€!

3개의 μ’‹μ•„μš”