如何在不创建 ViewModel 对象的情况下指定 DataContext (ViewModel) 类型以在 XAML 编辑器中进行设计时绑定检查?

How do I specify DataContext (ViewModel) type to get design-time binding checking in XAML editor without creating a ViewModel object?

我可以这样指定 DataContext:

<Window ... >
    <Window.DataContext>
        <MainViewModel />
    </Window.DataContext>
    ...
</Window>

在这种情况下,WPF 将创建一个 MainViewModel 类型的对象并将其分配给 window 的 DataContext 属性(这发生在 Window 的 InitializeComponent()方法)。

但是如果我的 ViewModel 没有默认构造函数怎么办。或者,如果我想在 Window.InitializeComponent() 执行后初始化 ViewModel 并将其分配给 DataContext(在 Window 的构造函数内或从实例化 window 的相同代码)怎么办 - 在本例中为 WPF创建一个 ViewModel(在 InitializeComponent() 内),将其分配给 window 的 DataContext,然后我用另一个 ViewModel 实例覆盖它(我担心这里不必要的对象实例化)。

我希望能够指定 ViewModel 的一种类型,因此如果我在 {Binding} 中拼错 属性 名称(或在重命名属性),或者我可以通过单击(在 XAML 中){Binding PropertyName}.

中的 属性 名称来进行声明

如果您自己动手做 MVVM,那将是棘手的部分。

你的选择,基本上:

使用依赖注入

您可以在 Page/Window 的构造函数中注入 ViewModel 并在其中分配它。

虽然这有一些缺点。

  • 更难使用设计时视图模型
  • 无法再从 XAML 实例化视图

首先使用导航服务的 ViewModel

您将解析您的 ViewModel 并通过导航服务进行所有导航。在您的 ViewModel 中,您传递了 INavigationService。您可以使用 ViewModel 类型导航到视图。在它内部通过依赖注入实例化 ViewModel,然后实例化视图(基于命名约定或通过 DI 配置)

好一点,但仍然不允许您在 XAML 中实例化视图。最大的优点是,它允许您轻松地将参数传递给 ViewModel(让 ViewModels 使用 NavigatedTo 方法实现 INavigationAware 属性,在实例化并将参数传递给之后调用)

ViewModelLocator/附上Property/Behavior

有了这个,您将创建一个附加的 属性,您可以将其设置为 true(即自动装配)或 ViewModel 类型(以更好地控制实例化的 ViewModel)和查找并解析 ViewModel 并分配它。

它基本上提供了上述所有优点以及实例化形式的视图。

最后一个基本上是 Microsoft 的 MVVM 框架 "Prism" 所做的(导航服务 navigationService.Navigate("MyPage", myParameterForViewModel),通过自动装配从 XAML 进行 DataContext 实例化和分配(在 XAML 中:prism:ViewModelLocator.AutoWireViewModel="True").

也就是说,最好使用成熟的 MVVM 框架来完成这部分布线(即使您决定不使用基础 类,例如 BindableBase 或任何所谓的在所述框架内)。

关于 ViewModel 的设计时 ViewModel/auto-completition:

您可以使用 Blend 的设计时属性来执行此操作。您需要先添加 Blend 程序集引用。然后你可以将 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 命名空间添加到你的 page/view 中。

然后您可以通过d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}将其绑定到您的页面。注意 DataContext 之前的 d:,这很重要。此 DataContext 将仅在 Designer 中使用(Visual Studio XAML Designer 或在 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 还不是 finished/implemented。