public partial class TablePartyPage : ContentPage, IDisposable
{
private MyViewModel _vm;
[...]
protected override void OnAppearing()
{
base.OnAppearing();
Shell.Current.Navigating += OnNavigating;
}
protected override void OnDisappearing()
{
Shell.Current.Navigating -= OnNavigating;
base.OnDisappearing();
}
private async void OnNavigating(object sender, ShellNavigatingEventArgs args)
{
// I define constants for page routes and register them in AppShell,
// here I use those routes to allow certain navigation targets
if (args.Target.Location.OriginalString.EndsWith(AppShell.MyPageRoute)
|| args.Target.Location.OriginalString.EndsWith(AppShell.MyChildPageRoute))
{ // Navigating to this page or one of its children - allow this navigation
return;
}
else
{ // Navigating away from this page
if (!_vm.HasUnsavedChanges)
return; // No unsaved changes - allow navigation
// Pause navigation till the user makes a decision
var deferral = args.GetDeferral();
const string STAY = "Stay on this page";
const string DISCARD = "Discard changes";
switch (await DisplayActionSheet(
"There are unsaved changes on this page", null, null, STAY, DISCARD))
{
case STAY:
default:
// Do not leave this page, cancel navigation
args.Cancel();
break;
case DISCARD:
_vm.DiscardChanges();
break;
}
// Un-pause navigation
deferral.Complete();
}
}
}
1条答案
按热度按时间jchrr9hc1#
最后我使用了Page.onNavigating()事件,因为每次从我的页面进行导航时都会触发该事件。
但有一些警告:事件处理程序需要以一种巧妙的方式被注册和取消注册,以防止多次注册。
在事件处理程序中,我显示了一个用户对话框。在用户交互期间,导航必须暂停,并根据用户的决定执行或取消。在事件参数上有一个(截至本文撰写时)未记录的方法,称为GetDeferral(),我需要使用它。
我是这样实现的。
事件处理程序注册
我试着在构造函数中注册,在析构函数中注销,但是没有用。我使用依赖注入,页面被注册为 transient 。当导航离开页面时,析构函数还没有被调用,第二次查看该页将第二次注册该事件处理程序。将页注册更改为单一示例会导致页控件生存期出现问题。最终在OnAppearing/OnDisappearing方法:
在我的页面xaml.cs中: