Silverlight 4.0 MVVM和导航服务

Silverlight 4.0 MVVM和导航服务,silverlight-4.0,mvvm,mvvm-light,windows-phone-7.1,Silverlight 4.0,Mvvm,Mvvm Light,Windows Phone 7.1,实现任何模式的许多好处之一是在应用程序的不同层之间分离关注点。就Silverlight和MVVM而言,我认为导航服务属于UI 如果NavigationService属于UI,那么它应该在XAML代码中使用,但是命令发生在ViewModel上。我是否应该在ViewModel中的命令上引发一个事件,让视图处理该事件并调用导航?如果我只是简单地导航到另一个页面,那听起来有点荒谬。我不应该直接处理UI事件并从那里导航吗 查看控制事件->查看模型命令->引发事件->查看 已处理事件->导航 或 查看控制事

实现任何模式的许多好处之一是在应用程序的不同层之间分离关注点。就Silverlight和MVVM而言,我认为导航服务属于UI

如果NavigationService属于UI,那么它应该在XAML代码中使用,但是命令发生在ViewModel上。我是否应该在ViewModel中的命令上引发一个事件,让视图处理该事件并调用导航?如果我只是简单地导航到另一个页面,那听起来有点荒谬。我不应该直接处理UI事件并从那里导航吗

查看控制事件->查看模型命令->引发事件->查看 已处理事件->导航

查看控制事件->查看已处理事件->导航


有两种记录在案的方法来解决这个问题

  • 使用MVVM Light的消息功能实现导航

    此方法由Jesse Liberty在其MVVM Ligtht soup to nuts系列中提出。他的方法是从命令向视图发送一条消息,指示应该进行导航操作。

  • 实现一个处理导航的ViewService

    Jesse在文章中提到了这种方法。这实现了一个处理视图模型触发的所有导航操作的服务
  • 这两种方法都只处理WP7应用程序中的导航。但是,它们也可以适应Silverligt应用

    Jesse的方法更易于在SL中使用,因为它不需要访问根可视文件。但是,导航代码分布在多个地方,需要代码隐藏来执行实际的导航

    Laurent的方法需要访问根visual—用于访问内置导航功能。如Laurent的代码所示,在WP7应用程序中访问它并没有什么大不了的。然而,在SL应用程序中,它稍微复杂一些,因为没有sourrounding帧。然而,我已经在我的一个项目中使用附加属性实现了SL模式,并完成了所需的连接-因此,尽管需要更多的工作,但它也可用于SL


    因此,总结一下——虽然Jesse的方法更容易实现,但我个人更喜欢Laurent的方法,因为它是更干净的体系结构——不需要任何代码,功能被封装到一个单独的组件中,因此位于一个点上。

    这个问题有点晚了,但这是相关的,希望对某些人有益。我必须使用MvvmLight创建一个SL4应用程序,并希望使用一个可模拟的导航服务包装器,该包装器可以注入到ViewModel中。我在这里找到了一个很好的起点:Laurent Bugnon的来自Mix11的SL4示例代码示例,其中包括导航服务演示:

    下面是实现可用于Silverlight 4的模拟导航服务的基本部分。关键问题是获取对要在自定义NavigationService类中使用的主导航框架的引用

    1) 在MainPage.xaml中,导航框架被赋予一个唯一的名称,在本例中,它将是ContentFrame:

    3) 导航服务类实现INavigationService接口,并依赖MainPage.xaml.cs的NavigationFrame属性获取对导航框架的引用:

    INavigationService公共接口
    {
    事件导航CancelEventHandler导航;
    无效导航到(Uri);
    void GoBack();
    }
    公共类导航服务:INavigationService
    {
    专用帧主机;
    公共事件导航CancelEventHandler导航;
    public void NavigateTo(Uri页面Uri)
    {
    if(inframe())
    _大型机导航(pageUri);
    }
    公开作废GoBack()
    {
    if(EnsureMainFrame()&&&_mainFrame.CanGoBack)
    _mainFrame.GoBack();
    }
    二等兵
    {
    如果(_mainFrame!=null)
    返回true;
    var mainPage=(Application.Current.RootVisual作为mainPage);
    如果(主页!=null)
    {
    //****以下是对步骤1,2中先前公开的导航框架的引用
    _mainFrame=mainPage.NavigationFrame;
    如果(_mainFrame!=null)
    {
    //如果应用程序在设计工具内运行,则可能为null
    _大型机。导航+=(s,e)=>
    {
    如果(导航!=null)
    {
    航行(s,e);
    }
    };
    返回true;
    }
    }
    返回false;
    }
    }
    
    实际上,您可以选择如何实现模式以及如何解决此类问题。最好的做法可能是使用类似MVVM Ligh Messenger的消息传递,这样就可以从视图模型发送一条视图应该导航的消息,并在视图之间导航一个资源类或其他内容。:)优秀的响应和链接!
    <navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
        Source="/Home" Navigated="ContentFrame_Navigated"  
        NavigationFailed="ContentFrame_NavigationFailed">
        <!-- UriMappers here -->
    </navigation:Frame>