如何将 DataTemplate 数据类型绑定到接收 ViewModels 的视图,这是由 DI 注入的依赖项

How to bind a DataTemplate datatype to a View which receives ViewModels a dependency injected by DI

我有一个 WPF 应用程序,它使用 MVVM 实现导航,为同一 Window 中的每个视图填充不同的 DataTemplate,例如:

<Window.Resources>
    <DataTemplate DataType="{x:Type foo:FooViewModel}">
        <foo:FooView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type bar:BarViewModel}">
        <bar:BarView/>
    </DataTemplate>
<Window.Resources>

Switching between Views/UserControls using MVVM 是 Rachel Lim 的文章,它启发了上述方法)

现在发生的事情是 FooView 将 FooViewModel 作为依赖项自动注入 DI(在我的例子中是 Microsoft.Extensions.DependencyInjection on .Net Core3 Preview)例如:

public partial class FooView : UserControl
{
    public FooView(FooViewModel fooViewModel)
    {  
        this.InitializeComponent();
        this.DataContext = fooViewModel;
    }
}

此时 DataTemplate 显然会抱怨,因为 FooView 没有定义无参数构造函数(根据参考 Type '{0}' is not usable as an object element

有没有办法绕过这个问题,让 FooView 使用 FooViewModel 作为 DataContext?

数据模板

<DataTemplate DataType="{x:Type foo:FooViewModel}">
    <foo:FooView/>
</DataTemplate>

将 FooViewModel 的实例分配给 FooView.DataContext。

this.DataContext = fooViewModel; 行在 FooView 控件中是无用的,因为在这种情况下 DataContext 将被覆盖。我会说,通过 contrustor 传递视图模型是完全没问题的 而不是 。可以从 DataContext 访问它:

public partial class FooView : UserControl
{
    public FooView()
    {  
        this.InitializeComponent();
    }

    private FooViewModel Vm { get { return this.DataContext as FooViewModel; } }
}

在您使用的导航模式中,View 是 ViewModel 的接收者。当前 ViewModel 由 AppViewModel:

设置
public class AppViewModel
{
    // simplified properties
    public ViewModelBase CurrentViewModel {get; set;}
    public ICommand ViewFooCommand {get;}
    public ICommand ViewBarCommand {get;}
} 

您正在尝试使 View 成为 ViewModel 的 originator/producer,这与模式冲突。