我可以像这样指定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中)转到声明。
感谢您无价的时间。
答案 0 :(得分:40)
如果你做自己动手的MVVM,这是一个棘手的部分。
您的选择,基本上:
使用依赖注入
您可以在Page
/ Window
的构造函数中注入ViewModel并在其中分配。
但这有一些缺点。
首先使用导航服务的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设计师提供了使用它的机会。