从Windows Phone 8.1通用应用程序中的View Model导航到新页面

我正在开发一个Windows Phone 8.1通用应用程序,并希望找到处理页面导航的最佳方法,而不会在后面的代码中使用大量逻辑。 我希望尽可能整洁地将代码保留在我的视图中。 为响应按钮点击,导航到新页面的MVVM方式是什么?

我目前必须从ViewModel向视图发送一条RelayComnmand消息,其中包含要导航到的页面的详细信息。 这意味着后面的代码必须按如下方式连接:

public MainPage() { InitializeComponent(); Messenger.Default.Register(this, (article) => ReceiveOpenArticleMessage(article)); ... } private object ReceiveOpenArticleMessage(OpenArticleMessage article) { Frame.Navigate(typeof(ArticleView)); } 

虽然这确实有效,但这似乎并不是最好的方法。 如何直接从ViewModel进行页面导航? 我在我的项目中使用MVVM-Light。

好的,我找到了这个问题的答案。 进行了一些调查,但我最终找到了首选的MVVM-Light方式。 无论如何我都不赞成这个答案,只是将其发布在这里以防人们正在寻找这个问题的答案。

创建一个INavigationService接口,如下所示:

 public interface INavigationService { void Navigate(Type sourcePageType); void Navigate(Type sourcePageType, object parameter); void GoBack(); } 

创建一个NavigationService类,如下所示:

 public class NavigationService : INavigationService { public void Navigate(Type sourcePageType) { ((Frame)Window.Current.Content).Navigate(sourcePageType); } public void Navigate(Type sourcePageType, object parameter) { ((Frame)Window.Current.Content).Navigate(sourcePageType, parameter); } public void GoBack() { ((Frame)Window.Current.Content).GoBack(); } } 

现在在ViewModelLocator中,将其设置如下:

  [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This non-static member is needed for data binding purposes.")] public MainViewModel Main { get { return ServiceLocator.Current.GetInstance(); } } static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { SimpleIoc.Default.Register(); } else { SimpleIoc.Default.Register(() => new NavigationService()); } SimpleIoc.Default.Register(); } 

接下来设置导航服务的设计时间如下:

 public class DesignNavigationService : INavigationService { // This class doesn't perform navigation, in order // to avoid issues in the designer at design time. public void Navigate(Type sourcePageType) { } public void Navigate(Type sourcePageType, object parameter) { } public void GoBack() { } } 

我的MainViewModel构造函数如下:

  public MainViewModel(INavigationService navigationService) { _navigationService = navigationService; ... 

现在您可以使用它在viewmodel中导航:

 _navigationService.Navigate(typeof(WelcomeView)); 

有关原作者Laurent Bugnion的更多详细信息,请参阅此文章和相关代码。 http://msdn.microsoft.com/en-us/magazine/jj651572.aspx

这里有一个新的更简单的实现: https : //marcominerva.wordpress.com/2014/10/10/navigationservice-in-mvvm-light-v5/
首先我们创建NavigationServiceDialogService (用于页面导航参数):

 public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); var navigationService = this.CreateNavigationService(); SimpleIoc.Default.Register(() => navigationService); SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); } private INavigationService CreateNavigationService() { var navigationService = new NavigationService(); navigationService.Configure("Details", typeof(DetailsPage)); // navigationService.Configure("key1", typeof(OtherPage1)); // navigationService.Configure("key2", typeof(OtherPage2)); return navigationService; } 

然后我们在ViewModel创建一个RelayCommandNavigationService ,如下所示:

 public class MainViewModel : ViewModelBase { private INavigationService _navigationService; public RelayCommand> DetailsCommand { get; set; } public MainViewModel(INavigationService navigationService) { this._navigationService = navigationService; DetailsCommand = new RelayCommand>((args) => NavigateTo(args)); } public void NavigateTo(Tuple args) { this._navigationService.NavigateTo(args.Item1, args.Item1); } public void ClickAndNavigate() { NavigateTo(new Tuple("AdminPivotPage", "Test Params")); } } 

最后,我们可以像这样得到页面导航参数:

 public sealed partial class DetailsPage : Page { // ... protected override void OnNavigatedTo(NavigationEventArgs e) { var parameter = e.Parameter as string; // "My data" base.OnNavigatedTo(e); } } 

但是要阅读MVVM模式中页面导航中传递的参数,您可以在这里查看 。

我同意上面的ricochete ,它更简单,虽然我的直接暗示搞砸了我在Blend中的Design Data Binding。

我决定创建一个inheritance自NavigationService的类

 public class NavigationServiceHelper : NavigationService { public NavigationServiceHelper() { this.Configure("Page1", typeof(View.Page1)); this.Configure("Page2", typeof(View.Page2)); } } 

然后在ViewModelLocator中我以这种方式注册了它

  SimpleIoc.Default.Register(); 

我的设计视图数据绑定再次起作用。 如果有人能够解释为什么设计数据不能用于上面的弹性模板,请做。 谢谢!