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

时间:2015-04-01 19:25:46

标签: c# wpf xaml mvvm

我可以像这样指定DataContext:

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

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

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

我希望能够只指定InitializeComponent()的类型,所以如果我在{Binding}中拼错了一个属性名称(或重命名属性后),我会得到设计时警告,或者我可以通过单击{Binding PropertyName}内的属性名称(在XAML中)转到声明。

感谢您无价的时间。

1 个答案:

答案 0 :(得分:40)

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

您的选择,基本上:

使用依赖注入

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

但这有一些缺点。

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

首先使用导航服务的ViewModel

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

这有点好,但仍然不允许你在XAML中实例化视图。 Big plus是,它允许您轻松地将参数传递给ViewModel(具有ViewModels实现INavigationAware属性和NavigatedTo方法,该方法在实例化后调用并将参数传递给)

ViewModelLocator /附加属性/行为

使用这个,您将创建一个附加属性,您可以将其设置为true(即自动装配)或ViewModel类型(以便对实例化ViewModel进行更多控制)并查找并解析ViewModel并分配它。

它基本上给出了上面的所有优点以及View的实例化。

最后一个基本上是微软的MVVM框架&#34; Prism&#34; (导航服务navigationService.Navigate("MyPage", myParameterForViewModel),DataContext实例化以及通过自动装配从XAML分配(在XAML中:prism:ViewModelLocator.AutoWireViewModel="True")。

话虽这么说,最好使用一个成熟的MVVM框架来完成这部分的布线(即使你决定不使用诸如BindableBase之类的基类或其他基础类。在所述框架中呼吁。)

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

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

然后,您可以通过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使用Interfaces,那么创建设计实例的速度非常快,只需让Visual Studio实现所有Interface属性并为其提供一些默认值(对于属性,您可以在其中包含示例数据) ViewModel验证绑定是否正常工作)。

这需要您创建单独的设计时ViewModel和您的实际ViewModel,它们听起来并不像它那样糟糕。即使真正的ViewModel尚未完成/实现,这也为您的UI设计师提供了使用它的机会。