nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

Prism for Xamarin.Forms入門 IConfirmNavigationAsync

以前、NavigationServiceの解説回にてIConfirmNavigationの説明をしました。

Prism for Xamarin.Forms入門 NavigationService Deep Dive - nuits.jp blog

IConfirmNavigationは端的に言うと、画面遷移時に条件によって遷移を抑止することができる機能です。
昨日ひょんなことから、これの非同期版であるIConfirmNavigationAsyncを教えていただきました。
非常に感動したので早速みなさんにも共有したいと思い、このエントリーを書きました。
何が良いのかというと、次のような画面遷移時にダイアログで確認ダイアログを表示するようなことが非常に簡単に実現できます。

f:id:nuitsjp:20161015102832g:plain

なお本エントリーは連載記事「Prism for Xamarin.Forms入門」の一部となっております。
以下に目次がありますので、他のエントリーもご覧いただけると嬉しいです。
【Xamarin】Prism.Forms入門 目次 - nuits.jp blog

それでは簡単に説明していきたいと思います。

概要

IConfirmNavigationAsyncのメソッドの該当のメソッドのシグニチャは以下の通りです。

public Task<bool> CanNavigateAsync(NavigationParameters parameters) 

説明するまでもないかもしれませんが、画面遷移前に上記メソッドが呼び出され、trueを返せばそのまま遷移し、falseを返せば画面遷移がブロックされます。
本エントリーでは以下の二つの例を紹介します。

  1. AlertDialogを利用して遷移を確認する
  2. 遷移前に重たい処理をする際に、ProgressRingを表示する

なお本エントリーでは、NavigationServiceとPageDialigServiceの基本については理解しているものとして記述します。
ご存じない方は、まずは以下のリンク先をご一読ください。

Prism for Xamarin.Forms入門 NavigationService Quickstart - nuits.jp blog
Prism for Xamarin.Forms入門 NavigationService Deep Dive - nuits.jp blog
Prism for Xamarin.Forms入門 PageDialogService - nuits.jp blog

また、実装例はGithubの以下のリポジトリ内に置いてありますので、ConfirmNavigationAsync.slnを確認してみてください。

github.com

AlertDialogを利用して遷移を確認する

こちらは非常に簡単です。
まずViewModelでIConfirmNavigationAsyncを実装します。
IConfirmNavigationAsyncサービスは3つのメソッドを持ちます。

  1. OnNavigatedTo
  2. OnNavigatedFrom
  3. CanNavigateAsync

今回は1. 2. の説明は割愛します。
主役はCanNavigateAsyncです。
CanNavigateAsyncメソッドを以下のように実装します。

public Task<bool> CanNavigateAsync(NavigationParameters parameters)
{
    return _pageDialogService.DisplayAlertAsync("title", "confirm message", "OK", "Cancel");
}

DisplayAlertAsyncの戻り値自体がTaskですので、ダイアログを起動して、それをそのまま返却すればOKです。
非常にお手軽ですね!

遷移前に重たい処理をする際に、ProgressRingを表示する

下の図のようなイメージです。

f:id:nuitsjp:20161015162123g:plain

まずXAMLです。

<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
  <Button Text="Navigate" Command="{Binding NavigateCommand}"/>
  <ActivityIndicator
                  HorizontalOptions="Center"
                  VerticalOptions="Center"
                  IsVisible="{Binding IsProcessing}"
                  IsEnabled="True"
                  IsRunning="{Binding IsProcessing}"/>
</StackLayout>

画面遷移用のボタンと、重たい処理の処理中を表すActivityIndicatorを置いてあります。
ActivityIndicatorのIsVisibleプロパティとIsRunningプロパティには、ViewModelのIsProcessingプロパティをバインドしています。
IsProcessingプロパティの状態を変更することで処理中の状態を制御します。

続いてViewModelです。
まずはIsProcessingです。

private bool _isProcessing;
public bool IsProcessing
{
    get { return _isProcessing; }
    set { SetProperty(ref _isProcessing, value); }
}

語ることはありません。
続いて重たい処理の、仮メソッドを用意します。

private Task ProcessHeavy()
{
    return Task.Delay(TimeSpan.FromSeconds(3));
}

3秒待つだけですね。
そして主役のCanNavigateAsyncです。

public async Task<bool> CanNavigateAsync(NavigationParameters parameters)
{
    IsProcessing = true;
    await ProcessHeavy();
    IsProcessing = false;
    return true;
}

ProcessHeavyの前後でIsProcessingの状態を変えて処理中を表示しています。
ProcessHeavyはTaskを返しますので、await使いたいですよねってことで、先ほどとは異なりCanNavigateAsyncの宣言にasync宣言をしています。
簡単すぎる!最高!

というわけで今日はここまで。
それではまた!