Подтвердить что ты не робот

Как перехватить кнопку навигации на панели навигации, нажатой в Xamarin Forms?

У меня есть страница формы xamarin, где пользователь может обновлять некоторые данные в форме. Мне нужно перехватить кнопку "Навигационная панель". Нажмите "Отправить", чтобы предупредить пользователя, если некоторые данные не были сохранены. Как это сделать?

Я могу перехватить аппаратную панель Bar Back Button, нажав на Android, используя Android.MainActivity.OnBackPressed(), но это событие поднимается только на аппаратной панели Back Button Clicked, а не на панели навигации Back Button Clicked.

Я также попытался переопределить Xamarin.Forms.NavigationPageOnBackButtonPressed(), но он не работает. Зачем? Кто-то уже решил эту проблему?

Я также попытался переопределить OnDisappear(), есть две проблемы:

  • Страница уже визуально исчезла, так что "Вы уверены?" на предыдущей странице появится диалоговое окно.
  • Невозможно отменить действие назад.

Итак, можно ли перехватить кнопку назад на панели навигации?

4b9b3361

Ответ 1

Мне удалось показать диалог подтверждения, который может отменить навигацию, переопределив следующие методы в 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];

Ответ 2

Самый простой, поскольку @JordanMazurke также несколько упоминает, поскольку событие для кнопки "Назад" не может быть обработано в настоящее время (кроме физической кнопки "Назад" для Android), либо:

  • NavigationPage.ShowHasBackButton(this, false)
  • Нажатие Modal вместо Page

Затем после этого вы можете добавить ActionbarItem, где вы можете обрабатывать Event.

Я лично говорил с командой iOS от Xamarin по этому вопросу, и они в основном сказали мне, что мы не должны ожидать поддержки обработки Event для BackButtonPressed в NavigationBar. Причина в том, что на iOS плохой практикой для пользователей получать сообщение при нажатии Back.

Ответ 3

Это неотъемлемо трудная задача, и единственный способ, которым я обходился, состоял в том, чтобы полностью удалить кнопку "Назад", а затем обработать обратную навигацию с помощью кнопки "Сохранить".

Я провел краткий поиск форума 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

Ответ 4

Как уже было сказано, вы не можете сделать эту кросс-платформу. Однако вы можете справиться с этим, возможно, не так много усилий: https://theconfuzedsourcecode.wordpress.com/2017/03/12/lets-override-navigation-bar-back-button-click-in-xamarin-forms/

В этой статье рассматриваются iOS и Android. Если у вас есть проект UWP, вам придется забить свое собственное решение.

Изменить: Вот решение UWP! На самом деле это оказалось довольно просто - есть только одна кнопка назад и ее поддержка форм, поэтому вам просто нужно переопределить ContentPages 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);
        }           
    }

Ответ 5

В Xamarin.Forms класс Page имеет OnBackButtonPressed(), который вы можете использовать для всех платформ.