かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Prism.Forms 7.1 の新しい XAML でのナビゲーション定義

Xamarin.Forms 向けの Prism の 7.1 (2018/07/17 時点で preview)で便利な機能が追加されてたので紹介します。

ドキュメントページはこちら。

Xaml Navigation | Prism

これが無い時はどうしてた?

画面遷移するだけの DelegateCommand 型のプロパティを定義して CommandParameter で遷移先を指定したりするようなことをしてました。

こんな感じですね。

private DelegateCommand<string> _navigateCommand;

public DelegateCommand<string> NavigateCommand => _navigateCommand ?? (_navaigateCommand = new DelegateCommand<string>(NavigateExecute);

private void NavigateExecute(string page)
{
  await _navigationService.NavigateAsync(page);
}

XAML 側でこんな感じに使います。

<Button Text="Nav"
              Command="{Binding NavigateCommand}"
              CommandParameter="NextPage" />

XAML でのナビゲーション定義を使うとどうなる?

これを使うと画面遷移するだけでよければ ViewModel にコマンドを定義しなくてもよくなります。 しかも、パラメーターも渡せるし画面遷移可能かどうかの条件も指定できるので結構なケースで XAML だけで完結しそうです。

使い方は以下のような感じです。

  • xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms" の名前空間を定義
  • {prism:NavigateTo '遷移先'}
  • 戻るときは {prism:GoBack} で OK
  • 以下はオプション
    • CommandParameter に渡したい情報を設定可能
      • prism:NavigationParameters タグを CommandParameter に指定することで複数個のパラメータも指定可能
    • prism:Navigation.CanNavigate 添付プロパティに画面遷移の実行可否の条件を指定可能

使ってみよう

例えば以下のような MainPage.xaml を用意します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms"
             x:Class="NewNavLab.Views.MainPage"
             Title="{Binding Title}">

    <StackLayout HorizontalOptions="CenterAndExpand"
                 VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Switch x:Name="canGoBack" />
        <Entry x:Name="param" />
        <Button Text="Navigate"
                prism:Navigation.CanNavigate="{Binding IsToggled, Source={x:Reference canGoBack}}"
                Command="{prism:NavigateTo 'NextPage'}" 
                CommandParameter="{Binding Text, Source={x:Reference param}}" />
    </StackLayout>

</ContentPage>

Switch で画面遷移の可否、Entry で次のページに渡すパラメーターを指定しています。

NextPage は以下のような感じです。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms"
             Title="{Binding Title}"
             x:Class="NewNavLab.Views.NextPage">
    <StackLayout>
        <Label Text="NextPage" />
        <Label Text="{Binding Text}" />
        <Button Text="Back"
                Command="{prism:GoBack}" />
    </StackLayout>
</ContentPage>
using Prism.Navigation;

namespace NewNavLab.ViewModels
{
    public class NextPageViewModel : ViewModelBase
    {
        private string _text;
        public string Text
        {
            get { return _text; }
            set { SetProperty(ref _text, value); }
        }

        public NextPageViewModel(INavigationService navigationService) : base(navigationService)
        {
        }

        public override void OnNavigatedTo(INavigationParameters parameters)
        {
            if (parameters.TryGetValue(KnownNavigationParameters.XamlParam, out string text))
            {
                Text = text;
            }
        }
    }
}

XAML で定義したナビゲーションのパラメーターはデフォルトで KnownNavigationParameters.XamlParam という名前で渡ってくるので、それで取得できます。

実行すると以下のような感じで動きます。

f:id:okazuki:20180717114106g:plain

コードは以下に置いてあります。

github.com