Xamarin.Forms モーダル ページ

Xamarin.Forms ではモーダル ページがサポートされています。 モーダル ページは、そのタスクが完了するかキャンセルされるまで、他の操作ができない自己完結型のタスクを完了させるようユーザーに促します。 この記事では、モーダル ページに移動する方法について説明します。

この記事では、次のトピックについて説明します。

概要

モーダル ページは、Xamarin.Forms でサポートされている任意の Page の種類にすることができます。 次の図に示すように、モーダル ページを表示するために、アプリケーションからモーダル スタックにプッシュされ、アクティブ ページになります。

ページをモーダル スタックにプッシュする

次の図に示すように、前のページに戻るために、アプリケーションでは現在のページがモーダル スタックからポップされ、新しい最上位のページがアクティブ ページになります。

モーダル スタックからページをポップする

ナビゲーションを実行する

モーダル ナビゲーション メソッドは、任意の Page 派生型の Navigation プロパティによって公開されます。 これらのメソッドは、モーダル スタックにモーダル ページをプッシュし、モーダル スタックからモーダル ページをポップする機能を提供します。

Navigation プロパティでは、モーダル スタック内のモーダル ページを取得する ModalStack プロパティも公開されています。 ただし、モーダル スタックの操作を実行したり、モーダル ナビゲーションで、ルート ページにポップしたりする概念はありません。 これは、これらの操作が基になるプラットフォームで一般にサポートされていないためです。

Note

NavigationPage インスタンスは、モーダル ページ ナビゲーションの実行には不要です。

モーダル スタックにページをプッシュする

ModalPage にナビゲートするには、次のコード例で示すように、現在のページの Navigation プロパティで PushModalAsync メソッドを起動する必要があります。

async void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
  if (listView.SelectedItem != null) {
    var detailPage = new DetailPage ();
    ...
    await Navigation.PushModalAsync (detailPage);
  }
}

これにより、MainPage インスタンス上の ListView で項目が選択されている場合は、ModalPage インスタンスがモーダル スタックにプッシュされ、アクティブ ページになります。 次のスクリーンショットに ModalPage インスタンスを示します。

モーダル ページの例

PushModalAsync が呼び出されると、次のイベントが発生します。

  • 基となるプラットフォームが Android ではない場合、PushModalAsync を呼び出すページでは、OnDisappearing のオーバーライドが呼び出されます。
  • ナビゲート先のページでは、OnAppearing のオーバーライドが呼び出されます。
  • PushAsync タスクが完了します。

ただし、これらのイベントが発生する正確な順序はプラットフォームによって異なります。 詳細については、Charles Petzold 氏著作の Xamarin.Forms ブックの第 24 章を参照してください。

Note

OnDisappearing および OnAppearing のオーバーライドの呼び出しは、ページ ナビゲーションを示す保証として扱うことはできません。 たとえば、iOS では、アプリケーションの終了時にアクティブ ページで OnDisappearing のオーバーライドが呼び出されます。

モーダル スタックからページをポップする

アクティブ ページは、これが物理的なボタンであるか画面上のボタンであるかどうかにかかわらず、デバイスの [戻る] ボタンを押すことによってモーダル スタックからポップすることができます。

元のページにプログラムを使用して戻るには、ModalPage インスタンスが、次のコード例のとおり PopModalAsync メソッドを起動する必要があります。

async void OnDismissButtonClicked (object sender, EventArgs args)
{
  await Navigation.PopModalAsync ();
}

これにより、モーダル スタックから ModalPage インスタンスが削除され、新しい最上位のページがアクティブ ページとなります。 PopModalAsync が呼び出されると、次のイベントが発生します。

  • PopModalAsync を呼び出すページでは、OnDisappearing のオーバーライドが呼び出されます。
  • 基となるプラットフォームが Android ではない場合、戻り先のページでは、OnAppearing のオーバーライドが呼び出されます。
  • PopModalAsync タスクが復帰します。

ただし、これらのイベントが発生する正確な順序はプラットフォームによって異なります。 詳細については、Charles Petzold 氏著作の Xamarin.Forms ブックの第 24 章を参照してください。

[戻る] ボタンを無効にする

Android では、デバイスの標準の [戻る] ボタンを押して、いつでも前のページに戻ることができます。 モーダル ページで、ユーザーがページから離れる前に自己完結型タスクを完了する必要がある場合は、アプリケーションで [戻る] ボタンを無効にする必要があります。 これを実現するには、モーダル ページの Page.OnBackButtonPressed メソッドをオーバーライドします。 詳細については、Charles Petzold 氏著作の Xamarin.Forms ブックの第 24 章を参照してください。

ページ遷移をアニメーション化する

各ページの Navigation プロパティには、次のコード例に示すように、ナビゲーション中にページ アニメーションを表示するかどうかを制御する boolean パラメーターを含むオーバーライドされたプッシュおよびポップ メソッドも用意されています。

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PushModalAsync (new DetailPage (), false);
}

async void OnDismissButtonClicked (object sender, EventArgs args)
{
  // Page appearance not animated
  await Navigation.PopModalAsync (false);
}

boolean パラメーターを false に設定すると、ページ遷移アニメーションが無効になります。また、パラメーターを true に設定すると、基となるプラットフォームでサポートされている場合はページ遷移アニメーションが有効になります。 ただし、プッシュとポップのメソッドでこのパラメーターが指定されていない場合は、既定でアニメーションが有効になります。

ナビゲーション時にデータを渡す

場合によっては、ナビゲーション中に、あるページから別のページにデータを渡す必要があります。 これを実現する 2 つの手法では、ページ コンストラクターを介してデータを渡し、新しいページの BindingContext をデータに設定しています。 これから、それぞれについて順番に説明します。

ページ コンストラクターを介してデータを渡す

ナビゲーション中に別のページにデータを渡す最も簡単な手法は、次のコード例で示すように、ページ コンストラクター パラメーターを使用することです。

public App ()
{
  MainPage = new MainPage (DateTime.Now.ToString ("u")));
}

このコードでは、現在の日付と時刻を ISO8601 形式で渡す MainPage インスタンスを作成します。

MainPage インスタンスは、次のコード例に示すように、コンストラクター パラメーターを使用してデータを受け取ります。

public MainPage (string date)
{
  InitializeComponent ();
  dateLabel.Text = date;
}

データは、Label.Text プロパティを設定することでページに表示されます。

BindingContext を介してデータを渡す

ナビゲーション中に別のページにデータを渡すもう 1 つの方法は、次のコード例に示すように、新しいページの BindingContext をデータに設定することです。

async void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
  if (listView.SelectedItem != null) {
    var detailPage = new DetailPage ();
    detailPage.BindingContext = e.SelectedItem as Contact;
    listView.SelectedItem = null;
    await Navigation.PushModalAsync (detailPage);
  }
}

このコードでは、DetailPage インスタンスの BindingContextContact インスタンスに設定し、DetailPage にナビゲートします。

次の XAML コード例に示すように、DetailPage ではデータ バインディングを使用して Contact インスタンス データを表示します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ModalNavigation.DetailPage">
    <ContentPage.Padding>
      <OnPlatform x:TypeArguments="Thickness">
        <On Platform="iOS" Value="0,40,0,0" />
      </OnPlatform>
    </ContentPage.Padding>
    <ContentPage.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <StackLayout Orientation="Horizontal">
                <Label Text="Name:" FontSize="Medium" HorizontalOptions="FillAndExpand" />
                <Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
            </StackLayout>
              ...
            <Button x:Name="dismissButton" Text="Dismiss" Clicked="OnDismissButtonClicked" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

次のコード例は、C# でデータ バインディングを実行する方法を示しています。

public class DetailPageCS : ContentPage
{
  public DetailPageCS ()
  {
    var nameLabel = new Label {
      FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
      FontAttributes = FontAttributes.Bold
    };
    nameLabel.SetBinding (Label.TextProperty, "Name");
    ...
    var dismissButton = new Button { Text = "Dismiss" };
    dismissButton.Clicked += OnDismissButtonClicked;

    Thickness padding;
    switch (Device.RuntimePlatform)
    {
        case Device.iOS:
            padding = new Thickness(0, 40, 0, 0);
            break;
        default:
            padding = new Thickness();
            break;
    }

    Padding = padding;
    Content = new StackLayout {
      HorizontalOptions = LayoutOptions.Center,
      VerticalOptions = LayoutOptions.Center,
      Children = {
        new StackLayout {
          Orientation = StackOrientation.Horizontal,
          Children = {
            new Label{ Text = "Name:", FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)), HorizontalOptions = LayoutOptions.FillAndExpand },
            nameLabel
          }
        },
        ...
        dismissButton
      }
    };
  }

  async void OnDismissButtonClicked (object sender, EventArgs args)
  {
    await Navigation.PopModalAsync ();
  }
}

データは、一連の Label コントロールによってページに表示されます。

データ バインディングの詳細については、「Data Binding Basics」 (データ バインディングの基礎) を参照してください。

まとめ

この記事では、モーダル ページに移動する方法について説明しました。 モーダル ページは、そのタスクが完了するかキャンセルされるまで、他の操作ができない自己完結型のタスクを完了させるようユーザーに促します。