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

How to handle the back button on WP 8.1 using MVVM light?

我正在寻找合适的方法来处理 Windows Phone 8.1 WinRT 上的后退按钮按下事件,使用 MVVM light 5 上可用的 NavigationService

到目前为止,我认为最好的地方是在 ViewModelLocator 中注册 NavigationServiceGoBack 方法,同时按照 [=15] 中概述的方法创建它=]

这是一种有效的方法。但是,我无法在返回之前处理验证,所以我想知道是否有更合适的方法来处理此事件。

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 post

Calling ViewModel methods in response to Page navigation events using MVVM Light in WinRT

您会注意到他使用 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() 中定义验证代码,并且 return 如果可以返回则返回 true,否则返回 false。

根据 igrali 的回答,并按照 Calling ViewModel methods in response to Page navigation events using MVVM Light in WinRT 中的说明,我在 "BindablePage.cs" class 中所做的是在 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

将这些新代码段括起来

我发现了一篇关于您的问题的有趣文章: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<INavigationService>();
            navigation.GoBack();
            e.Handled = true;
   }
 }