web-dev-qa-db-ja.com

Xamarinフォームでクリックされたナビゲーションバーの戻るボタンをインターセプトする方法

ユーザーがフォームの一部のデータを更新できるxamarinフォームページがあります。一部のデータが保存されていない場合、ナビゲーションバーの[戻る]ボタンをクリックしてユーザーに警告するようにインターセプトする必要があります。方法

Android Android.MainActivity.OnBackPressed()を使用してクリックしたハードウェアバーの戻るボタンをインターセプトできますが、そのイベントはハードウェアバーの戻るボタンをクリックしたときにのみ発生し、ナビゲーションバーでは発生しません戻るボタンがクリックされました。

Xamarin.Forms.NavigationPageOnBackButtonPressed()もオーバーライドしようとしましたが、機能しません。どうして?誰かがすでにその問題を解決していますか?

OnDisappear()をオーバーライドして試したところ、2つの問題があります。

  1. ページは既に視覚的に消えているため、「本当によろしいですか?」前のページにダイアログが表示されます。
  2. 戻るアクションはキャンセルできません。

では、ナビゲーションバーの戻るボタンの押下を遮断することは可能ですか?

14
Amrut

FormsApplicationActivityで以下のメソッドをオーバーライドすることで、ナビゲーションをキャンセルできる確認ダイアログを表示できました。

  // navigation back button
  public override bool OnOptionsItemSelected(IMenuItem item)
  {
     if (item.ItemId == 16908332)
     {
        var currentViewModel = (IViewModel)navigator.CurrentPage.BindingContext;
        currentViewModel.CanNavigateFromAsync().ContinueWith(t =>
        {
           if (t.Result)
           {
              navigator.PopAsync();
           }
        }, TaskScheduler.FromCurrentSynchronizationContext());
        return false;
     }
     else
     {
        return base.OnOptionsItemSelected(item);
     }
  }

  // hardware back button
  public async override void OnBackPressed()
  {
     var currentViewModel = (IViewModel)navigator.CurrentPage.BindingContext;

     // could display a confirmation dialog (ex: "Cancel changes?")
     var canNavigate = await currentViewModel.CanNavigateFromAsync();
     if (canNavigate)
     {
        base.OnBackPressed();
     }
  }

Navigator.CurrentPageは、INavigationサービスのラッパーです。モーダルページからのナビゲーションをキャンセルする必要がないので、NavigationStackのみを処理します。

this.navigation.NavigationStack[this.navigation.NavigationStack.Count - 1];
9
barry

@JordanMazurkeも多少言及しているように、最も簡単なのは、現在(Androidの物理的な戻るボタン以外の)戻るボタンのイベントを処理できないためです。

  1. NavigationPage.ShowHasBackButton(this, false)
  2. Modalの代わりにPageをプッシュする

その後、ActionbarItemを処理できる場所からEventを追加できます。

私はこの問題についてXamarinからiOSチームに個人的に話しました、そして彼らは基本的にEventBackButtonPressedNavigationBarを処理するためのサポートを期待すべきではないと私に言った。その理由は、iOSではBackが押されたときにユーザーがメッセージを受信することは悪い習慣だからです。

3
Demitrian

これは本質的に難しいタスクであり、私がそれを回避した唯一の方法は、戻るボタンを完全に削除してから、「保存」ボタンからの後方ナビゲーションを処理することでした。

Xamarin.Formsフォーラムを簡単に検索したところ、次のことが提案されました。

public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
{
    return false;
}

投稿のリンクは次のとおりです。

https://forums.xamarin.com/discussion/21631/is-there-nay-way-of-cancelling-the-back-button-event-from-the-navigationpage

0
JordanMazurke

すでに述べたように-このクロスプラットフォームはできません。ただし、おそらくそれほど努力することなくネイティブで処理できます。 https://theconfuzedsourcecode.wordpress.com/2017/03/12/lets-override-navigation-bar-back-button-click-in- xamarin-forms /

この記事ではiOSとAndroidについて説明します。 UWPプロジェクトがある場合は、そのための独自のソリューションを実行する必要があります。

編集:これはUWPソリューションです!実際には非常に簡単であることがわかりました。戻るボタンは1つだけで、フォームでサポートされているため、ContentPageのOnBackButtonPressedをオーバーライドするだけです。

    protected override bool OnBackButtonPressed()
    {
        if (Device.RuntimePlatform.Equals(Device.UWP))
        {
            OnClosePageRequested();
            return true;
        }
        else
        {
            base.OnBackButtonPressed();
            return false;
        }
    }

    async void OnClosePageRequested()
    {
        var tdvm = (TaskDetailsViewModel)BindingContext;
        if (tdvm.CanSaveTask())
        {
            var result = await DisplayAlert("Wait", "You have unsaved changes! Are you sure you want to go back?", "Discard changes", "Cancel");

            if (result)
            {
                tdvm.DiscardChanges();
                await Navigation.PopAsync(true);
            }
        }
        else
        {
            await Navigation.PopAsync(true);
        }           
    }
0
AXE