如果您自己动手做 MVVM,那就是棘手的部分。
你的选择,基本上:
使用依赖注入
您可以在 Page/Window 的构造函数中注入 ViewModel 并在其中分配它。
但这有一些缺点。
- 更难使用设计时视图模型
- 无法再从 XAML 实例化视图
带导航服务的 ViewModel 优先
您将解析您的 ViewModel 并通过导航服务完成所有导航。在您的 ViewModels 中,您传递了一个 INavigationService。您可以使用 ViewModel 类型导航到视图。在其中通过依赖注入实例化 ViewModel,然后实例化 View(基于命名约定或通过 DI 配置)
这有点好,但仍然不允许您在 XAML 中实例化视图。最大的优点是,它允许您轻松地将参数传递给 ViewModel(让 ViewModels 使用 NavigatedTo 方法实现 INavigationAware 属性,该方法在实例化并将参数传递给之后调用)
ViewModelLocator / 附加属性/行为
有了这个,您将创建一个附加属性,您可以将其设置为true(即自动装配)或 ViewModel 类型(以更好地控制实例化的 ViewModel),然后查找并解析 ViewModel 并分配它。
它基本上提供了上述所有优点以及实例化表单视图。
最后一个基本上是微软的 MVVM 框架“Prism”所做的(导航服务navigationService.Navigate("MyPage", myParameterForViewModel),DataContext 实例化和通过自动装配从 XAML 分配(在 XAML 中:prism:ViewModelLocator.AutoWireViewModel="True")。
话虽如此,最好使用成熟的 MVVM 框架来完成这部分接线(即使您决定不使用基类,例如 BindableBase 或在所述框架中调用的任何内容)。
关于 ViewModels 的设计时 ViewModel/自动完成:
您可以使用 Blend 的 Design-Time 属性来执行此操作。您需要先添加 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 和您的实际 ViewModel,这并不像听起来那么糟糕。这使您的 UI 设计师有机会使用它,即使真正的 ViewModel 尚未完成/实现。