我正在寻找一种使用MVVM在Silverlight应用程序中支持导航的真正解耦方式。我正在尝试完成更多的模式的“纯粹”实现,其中UI与ViewModel完全分离,以便应用程序实际上可以在没有UI的情况下完全运行。为此,我需要在没有UI问题的情况下支持导航。
我有几个想法如何实现这一点(使用Messaging等)但没有提出一种将View“映射”到ViewModel的好方法,以便UI可以在ViewModel“时”显示相应的View。显示”。我记得很久以前发过一篇文章描述了这个问题的解决方案,但似乎无法在网上找到它。
有谁知道如何找到这篇文章或有任何解决这个问题的经验?
答案 0 :(得分:2)
所以这里有点冗长的描述我们最终做了什么:
首先,我们决定使用内置的页面导航框架。我们有多种原因,但由于它是内置的,并且也是Windows 8中的导航框架,我们选择尝试这种方法。
我还应该提到我们在应用程序中使用MVVM Light和MEF。 (这在下面发挥作用。)
为了使这项工作,我们创建了一个包含Frame控件的应用程序Shell(UserControl)。 Shell的DataContext被设置为ShellViewModel的一个实例,它暴露了一个CurrentPage属性(String类型)。然后我们将Frame的Source属性绑定到CurrentPage。这种方法类似于Rachel的应用级ViewModel。
ShellViewModel向Messenger注册以接收CurrentPageChanged消息。收到消息后,将更新CurrentPage属性,引发PropertyChanged事件并更新UI。该消息源自NavigationService(实现INavigationService并使用MEF注入/导入)。
NavigationService公开一个NavigateTo方法,该方法接受表示目标的ViewModel的字符串名称。此名称与导出时使用ViewModel的合同名称(使用MEF)匹配,并用于使用ViewModelLocator查找实例。
在NavigateTo方法中,我们使用ViewModelLocator检索ViewModel实例,在当前ViewModel上调用Deactivate(如果有),在新ViewModel上调用Activate,然后发送带有新视图名称的CurrentPageChanged消息作为参数。 Activate / Deactivate是ViewModel上的辅助方法,允许我们在ViewModel导航或导航时执行任何必要的任务。
这似乎运行良好,并为我们提供了一个非常MVVM-ish的实现,所有导航都通过INavigationService和消息传递与ViewModels隔离。
现在唯一的缺点是,虽然我们在代码中使用字符串常量来表示ViewModel名称,但我们仍然在视图中对字符串进行硬编码以设置DataContext。我将研究一种自动设置DataContext的方法,作为导航“工具”的一部分。
我应该提一下,这种方法是从许多来源一起解析的,包括(但不限于)Rachel和以下链接:
http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/01/25/adapting-silverlight-navigation-to-mvvm.aspx
http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx
http://www.geoffhudik.com/tech/2010/10/10/another-wp7-navigation-approach-with-mvvm.html
答案 1 :(得分:1)
通常我对整个应用都有一个ViewModel
,它包含CurrentPage
和所有导航事件处理。
在View
方面,我使用ContentControl
,Content
绑定到CurrentPage
,然后使用DataTemplateSelector
确定View
ViewModel
}显示DataTemplates
如果您感兴趣,可以使用示例here,但它使用DataTemplateSelector
代替{{1}}。