如果您选择自己实现MVVM,那就是棘手的部分。
基本上有几种选择:
使用依赖注入
您可以在Page
/Window
构造函数中注入ViewModel,并在其中分配它。
但这有一些缺点:
- 更难使用设计时视图模型
- 无法再从XAML中实例化视图
首先使用ViewModel并使用导航服务
您将解决ViewModels并通过导航服务进行所有导航。在您的ViewModels中,您传递一个INavigationService
。您可以通过使用ViewModel类型导航到视图。在其中通过依赖注入实例化ViewModel,然后实例化视图(基于命名约定或通过DI配置)
这比较好,但仍然无法在XAML中实例化视图。最大的优点是,它允许您轻松地将参数传递给ViewModel(使ViewModels实现带NavigatedTo
方法的INavigationAware
属性,在实例化和传递参数后调用该方法)。
ViewModelLocator / 附加属性/行为
使用此方法,您可以创建一个附加属性,将其设置为true
(即自动连接)或ViewModel类型(以对实例化的ViewModel具有更多控制权),然后查找和解析ViewModel并分配它。
基本上,它提供了以上所有优点以及从View实例化。
最后一个基本上是微软的MVVM框架“Prism”所做的(通过导航服务navigationService.Navigate("MyPage", myParameterForViewModel)
,从XAML中通过自动连接实例化和分配DataContext(在XAML中:prism:ViewModelLocator.AutoWireViewModel="True"
)。
也就是说,最好使用成熟的MVVM框架来处理你的部分工作(即使你决定不使用基础类,如BindableBase
或其他在该框架中称为的类)。
至于设计时ViewModel/自动完成ViewModel:
您可以使用Blend的设计时属性来完成这个任务。首先需要添加Blend程序集引用。然后您可以将xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
命名空间添加到您的页面/视图中。
然后,您可以通过d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}
将其绑定到页面中。注意在DataContext之前加上 d:
,这很重要。此DataContext仅在设计器(Visual Studio XAML设计器或Blend中)中使用。这是为了防止干扰常规的DataContext
(没有前缀)。
例如:
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:myApp="clr-namespace:WpfApplication1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance myApp:Window2ViewModel, IsDesignTimeCreatable=True}">
<Grid>
<TextBlock Text ="{Binding Test}"/>
</Grid>
</Window>
如果您在ViewModel中使用接口,那么创建设计实例就非常快速,只需要让Visual Studio实现所有接口属性并为其赋一些默认值(例如属性的示例数据,以便验证绑定是否正确)。
这需要您创建单独的设计时ViewModel和实际的ViewModel,但这并没有听起来那么糟糕。这使您的UI设计师有机会使用它,即使真正的ViewModel尚未完成/实现。