如何在不创建 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?

查看:16
本文介绍了如何在不创建 ViewModel 对象的情况下指定 DataContext (ViewModel) 类型以在 XAML 编辑器中进行设计时绑定检查?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以像这样指定 DataContext:

I can specify DataContext like this:

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

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

And in this case WPF will create an object of type MainViewModel and assign it to the window's DataContext property (this happens inside Window's InitializeComponent() method).

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

But what if my ViewModel doesn't have a default constructor. Or what if I want to initialize ViewModel and assign it to DataContext after Window.InitializeComponent() is executed (inside Window's constructor or from the same code which instantiates the window) - in this case WPF creates a ViewModel (inside InitializeComponent()), assigns it to window's DataContext and then I overwrite it with another instance of ViewModel (I'm worried about unnecessary object instantiation here).

我希望能够仅指定一种 ViewModel,因此如果我在 {Binding} 中拼错了属性名称(或在重命名属性后),我会收到设计时警告,或者我可以通过单击(在 XAML 中){Binding PropertyName} 中的属性名称来转到声明.

I would like to be able to specify just a type of ViewModel, so I would get design-time warning if I misspell a property name inside {Binding} (or after renaming the property), or I could Go To Declaration by clicking (in XAML) on a property name inside {Binding PropertyName}.

感谢您的宝贵时间.

推荐答案

如果您自己动手做 MVVM,这就是棘手的部分.

That's the tricky part if you do the do-it-yourself MVVM.

您的选择,基本上:

使用依赖注入

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

You could inject the ViewModel in your Page/Window's constructor and assign it within it.

不过,这有一些缺点.

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

ViewModel First with Navigation Service

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

You'd resolve your ViewModels and do all your navigation via a navigation service. In your ViewModels you pass the an INavigationService. You could navigate to a view by using ViewModel type. Inside it instantiate the ViewModel via Dependency Injection, then instantiate the View (based on naming conventions or via DI configuration)

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

That's a bit better, but still won't allow you to instantiate the Views within XAML. Big plus is, it allows you easily to pass parameters to the ViewModel (having the ViewModels implement INavigationAware property with NavigatedTo method, which is called after instantiation and passing the parameter to)

ViewModelLocator/附加属性/行为

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

With this one, you would create an attached property, which you either set to true (i.e. autowire) or to a ViewModel type (to have more control over the ViewModel instantiated) and the find and resolve the ViewModel and assign it.

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

It basically gives all of the advantages above plus instantiation form View.

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

Last one is basically what Microsoft's MVVM framework "Prism" does (navigation service navigationService.Navigate("MyPage", myParameterForViewModel), DataContext instantiation and assignment from XAML via autowireing (In XAML: prism:ViewModelLocator.AutoWireViewModel="True").

话虽如此,最好使用成熟的 MVVM 框架来完成这部分接线(即使您决定不使用诸如 BindableBase 之类的基类或在所述框架中调用的任何内容)).

That being said, it's best to use an matured MVVM Framework which does this parts of your wiring (even if you decide not to use the base classes such as BindableBase or whatever it's called in said framework).

至于设计时 ViewModel/ViewModel 的自动完成:

As for design-time ViewModel/auto-completition for ViewModels:

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

You can use Blend's Design-Time attributes to do this. You need to add the Blend assembly references first. Then you can add xmlns:d="http://schemas.microsoft.com/expression/blend/2008" namespace into your page/view.

然后您可以通过 d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True} 将其绑定到您的页面中.注意 d: 之前的DataContext,这很重要.这个DataContext只会在Designer(Visual Studio XAML Designer或Blend)中使用.这是为了防止干扰正常的DataContext(没有前缀).

Then you can bind it into your page via d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}. Notice the d: before the DataContext, this is important. This DataContext will only be used in the Designer (Visual Studio XAML Designer or in Blend). This is to prevent interfering with the normal DataContext (without the prefix).

示例:

<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 中有示例数据以验证绑定正常工作).

If you use Interfaces for your ViewModels, it's pretty fast to create the Design Instance, by simply having Visual Studio implement all the Interface property and give it some default values (for property so you have example data in your ViewModel to verify bindings work correctly).

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

This requires you to create separate design-time ViewModels and your actual ViewModels, which isn't as bad as it sounds. This gives your UI designer the chance to work with it, even if the real ViewModel isn't finished/implemented yet.

这篇关于如何在不创建 ViewModel 对象的情况下指定 DataContext (ViewModel) 类型以在 XAML 编辑器中进行设计时绑定检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆