8. [.NET MAUI] INavigation 으로 Page(View) 전환하기
MainPage의 Button을 클릭했을 때 새로운 Page(View)로 넘어가는 기능을 구현해보자.
+ 추가로 Page에서 Root Page로 돌아가는 기능도 구현해본다.
이 기능을 구현하기 위해서 INavigation이라는 인터페이스가 필요하다.
- INavigation 참고자료
https://docs.microsoft.com/ko-kr/dotnet/api/xamarin.forms.inavigation?view=xamarin-forms
INavigation 인터페이스 (Xamarin.Forms)
플랫폼별 탐색을 추상화하는 인터페이스입니다.
docs.microsoft.com
1. MainPage_ViewModel.cs 소스에 INavigation을 전역으로 선언한다.
public INavigation MovePage_Navigation { get; set; }
"MovePage_Navigation"으로 선언하였다.
1-1. MainPage_ViewModel에 INavigation을 매개변수(파라미터)로 받는 생성자를 추가로 작성하고, 그안에 Command Click_Btn10을 아래와 같이 작성한다.
public MainPage_ViewModel(INavigation navigation)
{
MovePage_Navigation = navigation; //전역으로 선언한 Navigation에 파라로 받은 값 입력
Click_Btn10 = new Command(async () => //비동기를 위해 async
{
await MovePage_Navigation.PushAsync(new Page1()); //비동기식 호출을 대기를 위해 await
},
() =>
{
return true;
});
}
Command를 비동기 호출로 작성한다.
- 비동기 동기 호출에 대한 참고자료
async 및 await를 사용한 TAP(작업 비동기 프로그래밍) 모델(C#)
C#에서 비동기 프로그래밍에 대한 간소화된 접근 방식인 작업 기반 비동기 프로그래밍을 사용하는 시기 및 방법을 알아봅니다.
docs.microsoft.com
동기, 비동기 호출에 대해서
영어로는 Synchronous, Asynchronous Call
chanspark.github.io
2. MainPage.xaml 마크업 소스에 NavigationPage.TitleView를 추가하여 페이지에 Navigation 제목을 입력해준다.
2-1 Button의 Command Property에 ViewModel에 있는 "Click_Btn10" 를 바인딩 시킨다.
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:AppMaui.ViewModels"
x:Class="AppMaui.MainPage"
BackgroundColor="{DynamicResource SecondaryColor}">
<NavigationPage.TitleView>
<Label Text="Navigation Title"/>
</NavigationPage.TitleView>
<ScrollView>
<Grid Padding="20,60,20,60" HorizontalOptions="CenterAndExpand" VerticalOptions="StartAndExpand"
RowDefinitions="*,*,*,*,*"
ColumnDefinitions="*,*,*">
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" FontSize="Title"
Text="{Binding Row_Column }" />
<Button Grid.Row="1" Grid.Column="0" Text="1,0" Command="{Binding Click_Btn10}"/>
</Grid>
</ScrollView>
</ContentPage>
2-1. MainPage.xaml.cs (MainPage 코드 비하인드)에 BindingContext 부분을 INavigation을 파라로 받는 생성해준 생성자로 수정한다.
using AppMaui.ViewModels;
namespace AppMaui;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPage_ViewModel(Navigation);
}
}
3. Views 디렉토리에 새로운 Page를 추가한다.
3-1. Page1.xaml.cs (Page1 코드 비하인드)에도 동일하게 Navigation을 아래와 같이 적용해준다.
using AppMaui.ViewModels;
namespace AppMaui;
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
BindingContext = new Page1_ViewModel(Navigation);
}
}
3-2 Page1(View)의 ViewModel (Page1_ViewModel.cs) 도 추가로 생성한뒤 아래와 같이 작성해준다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AppMaui.Services;
using System.Windows.Input;
namespace AppMaui.ViewModels
{
class Page1_ViewModel : Notify
{
public INavigation nv_BackToMain { get; set; }
public ICommand cmd_BackToMain { get; set; }
public Page1_ViewModel()
{
}
public Page1_ViewModel(INavigation navigation)
{
nv_BackToMain = navigation;
cmd_BackToMain = new Command( () =>
{
nv_BackToMain.PopToRootAsync(); //처음 Navigation Root로 돌아가기
}, () =>
{
return true;
});
}
}
}
3-3 Page1.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="AppMaui.Page1"
Title="Page1"
BackgroundColor="White">
<NavigationPage.TitleView>
<Label Text="Page1"/>
</NavigationPage.TitleView>
<StackLayout>
<Grid RowDefinitions="*,*,*,*" ColumnDefinitions="*,*,*">
<Label Grid.Row="0" Grid.RowSpan="6" Grid.Column="0" Grid.ColumnSpan="3" Text="Label" FontSize="20"/>
<Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Text="BackToMain" Command="{Binding cmd_BackToMain}" />
</Grid>
</StackLayout>
</ContentPage>
4. 마지막으로 App.Xaml.cs (App.Xaml의 코드 비하인드)에 들어가서 아래와 같이 수정한다.
약 4시간을 허무하게 보낸 이 부분... (이 부분을 수정하지 않더라도 정상 빌드가 되기 때문에 찾기 힘들었다.)
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
이 소스를 수정하지않으면 PushModalAsync 은 동작하지만,(이것도... 새로운 Page가 Stack되기 전에 있는 Page의 컴포넌트가 눌리는 현상이 생김) PushAsync은 동작하지않는다.
5. 빌드해본다.
5-1 MainPage에서 버튼클릭 (Page1으로 이동)
5-2 Page1에서 Root Navigation인 MainPage로 이동
잘돌아간다.
끝!