C# 如何使用MVVM执行视图导航?赢RT

C# 如何使用MVVM执行视图导航?赢RT,c#,mvvm,navigation,win-universal-app,C#,Mvvm,Navigation,Win Universal App,我已经按照MVVM模式启动了一个Windows Universal项目,现在需要通过单击按钮导航到另一个页面 通常,我会在代码隐藏中使用按钮的单击事件来执行此操作,如下所示: private void AppBarButton_Click(object sender, RoutedEventArgs e) { // Navigation Without parameters this.Frame.Navigate(t

我已经按照MVVM模式启动了一个Windows Universal项目,现在需要通过单击按钮导航到另一个页面

通常,我会在代码隐藏中使用按钮的单击事件来执行此操作,如下所示:

        private void AppBarButton_Click(object sender, RoutedEventArgs e)
        {
            // Navigation Without parameters
            this.Frame.Navigate(typeof(SecondPage));

        }
但是,由于我需要在这个应用程序中遵循MVVM模式,我想知道如何在单击按钮时设置到新视图的导航


在谷歌搜索之后,我在WPF解决方案中遇到了这项任务的ICommand,但对于如何在这个Windows通用框架中实现它,我没有100%的了解。

基本上你有两个选择

1。使用导航服务

您可以定义一个
INavigationService
接口,并将其传递给viewmodel程序集中的所有viewmodel(假设您使用的是不同的程序集,这对于确保您没有引用viewmodel中的视图非常重要,从而违反MVVM模式)

在viewmodels中,您只需使用
navigationService.Navigate(“UserEditPage”,selectedUser.Id)调用它即可

实现可以简单到

public class WinRtNavigationService : INavigationService 
{
    public void Navigate(string page, object parameter) 
    {
        Type pageType = Type.GetType(string.Format("YourCompany.YourApp.ViewModels.{0}", page));
        ((Frame)Window.Current.Content).Navigate(pageType, parameter);
    }
}
如果需要从ViewModels导航,可以使用此选项

2。使用行为

您可以使用行为直接向XAML添加可重用的导航支持,从而完全避免代码隐藏

为此,Blend提供了交互性触发器和
NavigateToPageAction
行为

<Page 
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    xmlns:c="using:Microsoft.Xaml.Interactions.Core" >
    ....
    <Button Content="Edit">
        <i:Interaction.Behaviors>
            <i:BehaviorCollection>
                <c:EventTriggerBehavior EventName="Tapped">
                    <c:NavigateToPageAction TargetPage="YourCompany.YourApp.ViewModel.UserEditPage" Parameter="{Binding Path=SelectedUser.Id}" />
                </c:EventTriggerBehavior>
            </i:BehaviorCollection>

        </i:Interaction.Behaviors>
    </Button>
    ...
</Page>

....
...
混合行为/交互触发器通常用于将导航功能绑定到按钮或其他UI元素(即,单击不必是按钮的图片),因为它不需要代码隐藏或ViewModel中的任何代码


如果在一些验证之后进行导航,例如,您有一个用于用户注册的多页表单,您有一个绑定到
RegisterCommand
的“发送”按钮,
RegisterCommand
进行在线验证,您需要返回到上一页,那么您需要使用
INavigationService

“我需要在这个应用程序中遵循MVVM模式”如何排除使用代码隐藏?你通常的方法应该很管用。“MVVM”只处理程序的数据方面;隐式是控制器的概念,模式并不妨碍编写命令性代码来影响UI状态的更改,特别是当用户输入事件导致更改时。在代码背后连接导航不是最干净的方法,因为代码隐藏应该主要是空的,除了与视图相关的问题(动画、可重用的用户控件),因为在代码隐藏中编写的任何代码都与特定的视图紧密耦合(对于可重用的用户控件来说这很好)。Here@Tseng尝试了“行为”选项,但出现了一些与名称空间中不存在的行为相关的错误,请在下面的回答中留下评论。因此,决定了此解决方案的行为解决方案,并设法将其减少到6个错误,我已经添加了对行为SDK的引用,并在页面中定义了上述名称空间,但仍然得到了上述错误,有什么想法可以解决吗?您可能必须引用Blend Assemblies我已经添加了该引用,但是在ns中仍然找不到交互也尝试了不同的目标,“任何cpu”“x86”相同的错误,我只是注意到,您正在使用“url”命名空间(
xmlns:I
xmlns:ei
)而不是
xmlns:Interactivity
xmlns:Core
中定义的。尝试删除长的(交互性和核心),并将
i
ei
(在我的帖子
c
中)分别替换为
使用:Microsoft.Xaml.interactivity
使用:Microsoft.Xaml.Interactions.Core
<Page 
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    xmlns:c="using:Microsoft.Xaml.Interactions.Core" >
    ....
    <Button Content="Edit">
        <i:Interaction.Behaviors>
            <i:BehaviorCollection>
                <c:EventTriggerBehavior EventName="Tapped">
                    <c:NavigateToPageAction TargetPage="YourCompany.YourApp.ViewModel.UserEditPage" Parameter="{Binding Path=SelectedUser.Id}" />
                </c:EventTriggerBehavior>
            </i:BehaviorCollection>

        </i:Interaction.Behaviors>
    </Button>
    ...
</Page>