我已经使用HardwareButtons.BackPressed
事件注册了一个处理程序,执行了一些逻辑,然后在args中将handle属性设置为true(如果适用)。处理程序运行时没有任何问题,并且Handled属性已设置。手机仍会在应用程序外导航回来。我误解了如何使用这个活动吗?
public sealed partial class FirstRunPage : VisualStateAwarePage
{
public FirstRunPage()
{
this.InitializeComponent();
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed += (sender, args) =>
{
bool isHandled = false;
Action handledCallback = () => isHandled = true;
var state = new Dictionary<string, object> { { "Callback", handledCallback } };
((INavigationAware)this.DataContext).OnNavigatedTo("Back", NavigationMode.Back, state);
args.Handled = isHandled;
};
#endif
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
}
public override void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode, Dictionary<string, object> viewModelState)
{
if (navigationParameter == null || !navigationParameter.ToString().Equals("Back"))
{
return;
}
if (!viewModelState.ContainsKey("Callback"))
{
return;
}
var callback = (Action)viewModelState["Callback"];
// If the user is new, then we set it to false and invoke our callback.
if (this.IsNewUser)
{
this.IsNewUser = false;
callback();
}
else
{
return;
}
}
我修改了我的FirstRunPage以按照@Martin的建议订阅和取消订阅,但它仍然会关闭该应用。
public sealed partial class FirstRunPage : VisualStateAwarePage
{
public FirstRunPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed += HardwareBack_OnPressed;
#endif
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed -= HardwareBack_OnPressed;
#endif
}
private void HardwareBack_OnPressed(object sender, BackPressedEventArgs e)
{
Action handledCallback = () => e.Handled = true;
var state = new Dictionary<string, object> { { "Callback", handledCallback } };
((INavigationAware)this.DataContext).OnNavigatedTo("Back", NavigationMode.Back, state);
}
}
答案 0 :(得分:3)
在@yasen的帮助下,我能够解决这个问题。问题源于Prism库让您的App.xaml.cs继承自MvvmAppbase,它拦截BackPressed
事件。
为了解决这个问题,我重写了MvvmAppBase OnHardwareButtonsBackPressed
并添加了一些逻辑来处理它。
我的视图模型和视图都实现了一个名为INavigateBackwards的新接口,它们的使用方式如下:
public bool CanNavigateBack()
{
// If the new user is true, then we can't navigate backwards.
// There isn't any navigation stack, so the app will die.
bool canNavigate = !this.IsNewUser;
// Disable the new user mode.
this.IsNewUser = false;
// Return so that the view can return to it's sign-in state.
return canNavigate;
}
public sealed partial class FirstRunPage : VisualStateAwarePage, INavigateBackwards
{
private INavigateBackwards ViewModel
{
get
{
return (INavigateBackwards)this.DataContext;
}
}
public FirstRunPage()
{
this.InitializeComponent();
}
public bool CanNavigateBack()
{
return ViewModel.CanNavigateBack();
}
}
然后在MvvmAppBase子类中,我确定是否需要处理导航。
protected override void OnHardwareButtonsBackPressed(object sender, BackPressedEventArgs e)
{
var page = (Page)((Frame)Window.Current.Content).Content;
if (page is INavigateBackwards)
{
var navigatingPage = (INavigateBackwards)page;
if (!navigatingPage.CanNavigateBack())
{
e.Handled = true;
return;
}
}
base.OnHardwareButtonsBackPressed(sender, e);
}
这允许我的单个视图具有多个状态,用户可以从一个状态导航回到上一个状态而无需导航到全新视图。
答案 1 :(得分:0)
您的应用程序关闭的原因是同一个处理程序被调用的次数不止一次。第一个处理程序将Handled
属性设置为true
,但对同一事件触发的任何其他后续调用都会将其设置回false
。
为了说明一下,试试这个:
public sealed partial class FirstRunPage : VisualStateAwarePage
{
public FirstRunPage()
{
// ...
InitializeComponent();
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
bool isHandled = false;
Action handledCallback = () => isHandled = true;
var state = new Dictionary<string, object> { { "Callback", handledCallback } };
((INavigationAware)this.DataContext).OnNavigatedTo("Back", NavigationMode.Back, state);
args.Handled = isHandled;
};
}
并将断点设置为处理程序代码的最后一行。
要避免这种情况,请使用OnNavigatedTo
的{{1}}方法分配处理程序,并在FirstRunPage
中取消注册处理程序。
OnNavigatedFrom