我可以像这样指定DataContext:
<Window ... >
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
...
</Window>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,WPF将创建一个MainViewModel类型的对象,并将其分配给窗口的DataContext属性(这发生在Window的InitializeComponent()方法中).
但是如果我ViewModel没有默认构造函数怎么办呢.或者,如果我想初始化ViewModel并在Window.InitializeComponent()执行后将其分配给DataContext (在Window的构造函数内或从实例化窗口的相同代码中) - 在这种情况下,WPF创建一个ViewModel(内部InitializeComponent()),将其分配给窗口的DataContext,然后我用另一个ViewModel实例覆盖它(我担心这里不必要的对象实例化).
我希望能够只指定一种类型ViewModel,所以如果我在{Binding}中拼错一个属性名称(或重命名属性后),我会得到设计时警告,或者我可以通过点击(在XAML中转到声明) )在{Binding PropertyName}内的属性名称上.
谢谢你无价的时光.
Tse*_*eng 45
如果你做自己动手的MVVM,这是一个棘手的部分.
您的选择,基本上:
使用依赖注入
您可以在Page/ Window的构造函数中注入ViewModel 并将其分配给它.
这有一些缺点.
ViewModel首先使用导航服务
您将解析ViewModel并通过导航服务进行所有导航.在您的ViewModel中,您传递了一个INavigationService.您可以使用ViewModel类型导航到视图.在其中通过依赖注入实例化ViewModel,然后实例化View(基于命名约定或通过DI配置)
这有点好,但仍然不允许你在XAML中实例化视图.大加号是,它允许您轻松地将参数传递给ViewModel(具有ViewModels实现INavigationAware属性的NavigatedTo方法,在实例化后调用并将参数传递给)
ViewModelLocator /附加属性/行为
使用这个,您将创建一个附加属性,您可以将其设置为true(即自动装配)或ViewModel类型(以更好地控制实例化的ViewModel)并查找并解析ViewModel并分配它.
它基本上给出了上面的所有优点以及View的实例化.
最后一个基本上是微软的MVVM框架"Prism"所做的事情(导航服务navigationService.Navigate("MyPage", myParameterForViewModel),DataContext实例化以及通过自动装配从XAML分配(在XAML中prism:ViewModelLocator.AutoWireViewModel="True").
话虽这么说,最好使用一个成熟的MVVM框架来完成这部分的布线(即使你决定不使用诸如BindableBase所述框架中所谓的基类或其他基类).
至于ViewModel的设计时ViewModel/auto-completition:
您可以使用Blend的Design-Time属性来执行此操作.您需要先添加Blend程序集引用.然后,您可以将xmlns:d="http://schemas.microsoft.com/expression/blend/2008"命名空间添加到页面/视图中.
然后你可以通过它将它绑定到你的页面d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}.注意d:在DataContext之前,这很重要.此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>
Run Code Online (Sandbox Code Playgroud)
如果对ViewModel使用Interfaces,那么创建设计实例的速度非常快,只需让Visual Studio实现所有Interface属性并为其提供一些默认值(对于属性,您可以在ViewModel中使用示例数据来验证绑定是否正常工作) .
这需要您创建单独的设计时ViewModel和您的实际ViewModel,这并不像听起来那么糟糕.这使您的UI设计人员有机会使用它,即使尚未完成/实现真正的ViewModel.