简体   繁体   English

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

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

I'm searching for the appropiate way to handle the back button pressed event on Windows Phone 8.1 WinRT using the NavigationService available on MVVM light 5. 我正在寻找适当的方式来使用MVVM light 5上提供的NavigationService来处理Windows Phone 8.1 WinRT上的后退按钮事件。

So far I think the best place to do it is inside the ViewModelLocator by registering the GoBack method of the NavigationService while creating it following the approach outlined in NavigationService in MVVM Light V5 到目前为止,我认为最好的方法是在ViewModelLocator内部注册NavigationServiceGoBack方法,同时按照MVVM Light V5NavigationService中概述的方法创建它。

This is an effective approach. 这是一种有效的方法。 However, I can't handle validation before navigating back so I was wondering if there is a more suitable way to handle this event. 但是,在导航之前我无法处理验证,因此我想知道是否有更合适的方法来处理此事件。

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;
    }
}

If you take a look at how Marco is enabling OnNavigatedTo and OnNavigatedFrom calls to propagate to ViewModel in the blog post 如果你看一下Marco如何在博客文章中启用OnNavigatedTo和OnNavigatedFrom调用传播到ViewModel

Calling ViewModel methods in response to Page navigation events using MVVM Light in WinRT 使用WinRT中的MVVM Light调用ViewModel方法以响应页面导航事件

you'll notice he uses INavigable interface and Activate and Deactivate methods. 你会注意到他使用了INAVigable接口和Activate和Deactivate方法。 You could extend that INavigable interface with AllowGoingBack method, like this: 您可以使用AllowGoingBack方法扩展该INavigable接口,如下所示:

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

Each page-related ViewModel can then have its own implementation of AllowGoingBack method depending on the context. 然后,每个与页面相关的ViewModel都可以根据上下文自己实现AllowGoingBack方法。 Then, in the code behind of the View (which is OK, because View can know about the ViewModel) you can override OnNavigatingFrom and check if going back should be allowed: 然后,在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;
        }
    }
}

Your ViewModel would then implement INavigable, so you would define the validation code inside AllowGoingBack(), and return true if going back is OK, and false if it's not. 然后,您的ViewModel将实现INAVigable,因此您将在AllowGoingBack()中定义验证代码,如果返回,则返回true,如果不是,则返回false。

Based on the answer by igrali, and following the instructions in Calling ViewModel methods in response to Page navigation events using MVVM Light in WinRT , what I did in the "BindablePage.cs" class, in the OnNavigatedTo method was to add add the following: 根据igrali的回答,并按照WinRT中使用MVVM Light响应页面导航事件调用ViewModel方法中的说明,我在“BindablePage.cs”类中所做的,在OnNavigatedTo方法中添加以下内容:

            HardwareButtons.BackPressed += HardwareButtons_BackPressed;

and in the OnNavigatedFrom: 并在OnNavigatedFrom中:

            HardwareButtons.BackPressed -= HardwareButtons_BackPressed;

Then add the event handler: 然后添加事件处理程序:

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

Next, in the INavigable interface add 接下来,在INavigable界面中添加

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

And finally, on each view model: 最后,在每个视图模型上:

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 this is a universal app, then don't forget to surround these new pieces of code with #if WINDOWS_PHONE_APP ... #endif 如果这是一个通用应用程序,那么不要忘记用#if WINDOWS_PHONE_APP ... #endif包围这些新代码#if WINDOWS_PHONE_APP ... #endif

I found an interesting article about your question: http://blog.falafel.com/windows-phone-and-mvvm-light-navigationservice-and-cangoback/ 我发现了一篇关于你的问题的有趣文章: http//blog.falafel.com/windows-phone-and-mvvm-light-navigationservice-and-cangoback/

This is the idea: 这是个主意:

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;
   }
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM