C# 如何指定DataContext(ViewModel)类型以在XAML编辑器中进行设计时绑定检查,而不创建ViewModel对象?

C# 如何指定DataContext(ViewModel)类型以在XAML编辑器中进行设计时绑定检查,而不创建ViewModel对象?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我可以这样指定DataContext: <Window ... > <Window.DataContext> <MainViewModel /> </Window.DataContext> ... </Window> ... 在这种情况下,WPF将创建一个MainViewModel类型的对象,并将其分配给窗口的DataContext属性(这发生在窗口的InitializeComponent(

我可以这样指定DataContext:

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

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

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

我希望能够只指定一种类型的
ViewModel
,因此,如果我在{Binding}内(或重命名属性后)拼写错误,我将收到设计时警告,或者我可以通过单击{Binding PropertyName}内的属性名(在XAML中)转到声明


感谢您宝贵的时间。

如果您自己做MVVM,这是一个棘手的部分

你的选择,基本上是:

使用依赖项注入

您可以将ViewModel插入
页面
/
窗口
的构造函数中,并在其中分配它

但这也有一些缺点

  • 更难使用的设计时视图模型
  • 视图不能再从XAML实例化了
首先查看带有导航服务的模型

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

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

ViewModelLocator/附加属性/行为

使用此选项,您可以创建一个附加属性,将其设置为
true
(即autowire)或ViewModel类型(以便对实例化的ViewModel拥有更多控制权),然后查找和解析ViewModel并分配它

它基本上提供了上述所有优点,以及实例化表单视图

最后一个基本上是微软的MVVM框架“Prism”所做的(导航服务
navigationService.Navigate(“MyPage”,myParameterForViewModel)
,数据上下文实例化和通过自动连线从XAML分配(在XAML:
Prism:ViewModelLocator.AutoWireViewModel=“True”

这就是说,最好使用一个成熟的MVVM框架来完成这部分连接(即使您决定不使用诸如
BindableBase
之类的基类或在所述框架中调用的任何东西)

对于视图模型的设计时视图模型/自动完成:

您可以使用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设计器或混合)中使用。这是为了防止干扰正常的
数据上下文
(不带前缀)

例如:

<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>

如果为ViewModels使用接口,创建设计实例的速度非常快,只需让Visual Studio实现所有Interface属性并为其提供一些默认值(对于属性,您可以在ViewModel中使用示例数据来验证绑定是否正常工作)


这要求您创建单独的设计时视图模型和实际的视图模型,这并不像听起来那么糟糕。这使您的UI设计师有机会使用它,即使实际的视图模型尚未完成/实现。

Tseng,感谢您的回复。使用“使用依赖项注入”选项将不会进行设计时绑定检查,即在XAML编辑器中,我将得到“由于未知DataContext而无法解析符号XXX”警告。此外,我将无法单击“{binding PropertyName}”中的属性名称并自动跳转到属性声明。Tseng,我添加了一个示例(带有DesignInstance标记扩展名)在您的答案中。请有人批准它(我还没有足够的“能力”)。此外,我不必引用Blend assembly,我必须添加mc:Ignorable=“d”使其可编译。DesignInstance标记扩展解决了我的问题。谢谢。标记为答案。谢谢您的解决方案。IsDesignTimeCreatable=True