如何使用MVVM灯处理WP 8.1上的后退按钮?

我正在寻找适当的方法来使用MVVM light 5上提供的NavigationService来处理Windows Phone 8.1 WinRT上的后退按钮事件。

到目前为止,我认为最好的地方是在ViewModelLocator通过注册NavigationServiceGoBack方法,同时按照MVVM Light V5中NavigationService中概述的方法创建它。

这是一种有效的方法。 但是,我在导航之前无法处理validation,因此我想知道是否有更合适的方法来处理此事件。

 public class ViewModelLocator { public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); // Register NavigationService SimpleIoc.Default.Register(CreateNavigationService); // Register ViewModels here } private INavigationService CreateNavigationService() { var navigationService = new NavigationService(); // Register pages here navigationService.Configure("Details", typeof(DetailsPage)); // Handle back button HardwareButtons.BackPressed += (sender, args) => { navigationService.GoBack(); args.Handled = true; }; return navigationService; } } 

如果你看一下Marco如何在博客文章中启用OnNavigatedTo和OnNavigatedFrom调用传播到ViewModel

使用WinRT中的MVVM Light调用ViewModel方法以响应页面导航事件

你会注意到他使用了INAVigable接口和Activate和Deactivate方法。 您可以使用AllowGoingBack方法扩展该INavigable接口,如下所示:

 public interface INavigable { void Activate(object parameter); void Deactivate(object parameter); bool AllowGoingBack(); } 

然后,每个与页面相关的ViewModel都可以根据上下文自己实现AllowGoingBack方法。 然后,在View后面的代码中(可以,因为View可以了解ViewModel),您可以覆盖OnNavigatingFrom并检查是否应该允许返回:

 protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { var navigableViewModel = this.DataContext as INavigable; if (navigableViewModel != null) { if (e.NavigationMode == NavigationMode.Back && !navigableViewModel.AllowGoBack()) { e.Cancel = true; } } } 

然后,您的ViewModel将实现INAVigable,因此您将在AllowGoingBack()中定义validation代码,如果返回正常则返回true,否则返回false。

基于igrali的回答,并按照WinRT中使用MVVM Light响应页面导航事件调用ViewModel方法中的指示,我在“BindablePage.cs”类中在OnNavigatedTo方法中做的是添加以下内容:

  HardwareButtons.BackPressed += HardwareButtons_BackPressed; 

并在OnNavigatedFrom中:

  HardwareButtons.BackPressed -= HardwareButtons_BackPressed; 

然后添加事件处理程序:

  void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { var navigableViewModel = this.DataContext as INavigable; if (navigableViewModel != null) navigableViewModel.BackButonPressed(e); } 

接下来,在INavigable界面添加

 void BackButonPressed(Windows.Phone.UI.Input.BackPressedEventArgs e); 

最后,在每个视图模型上:

 public void BackButonPressed(Windows.Phone.UI.Input.BackPressedEventArgs e) { // You can modify this code to show a confirmation dialog, etc... e.Handled = true; navigationService.GoBack(); } 

如果这是一个通用应用程序,那么不要忘记用#if WINDOWS_PHONE_APP ... #endif包围这些新代码#if WINDOWS_PHONE_APP ... #endif

我发现了一篇关于你的问题的有趣文章: http : //blog.falafel.com/windows-phone-and-mvvm-light-navigationservice-and-cangoback/

这是个主意:

 public AboutPage() { this.InitializeComponent(); HardwareButtons.BackPressed += HardwareButtons_BackPressed; } private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) { var frame = Window.Current.Content as Frame; if (frame.CanGoBack) { var navigation = ServiceLocator.Current.GetInstance(); navigation.GoBack(); e.Handled = true; } }