【问题标题】:How to bind a DataTemplate datatype to a View which receives ViewModels a dependency injected by DI如何将 DataTemplate 数据类型绑定到接收 ViewModels DI 注入的依赖项的 View
【发布时间】:2019-08-16 08:53:49
【问题描述】:

我有一个 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 没有定义无参数 ctor(根据参考 Type '{0}' is not usable as an object element)

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

【问题讨论】:

  • 你需要这种依赖注入吗? DataTemplate 中的元素不应显式设置它们自己的 DataContext。相反,它将自动设置,例如到使用 DataTemplate 的 ContentControl 的 Content 值。
  • @Clemens 你是完全正确的。正如 Ash 指出的那样,我完全错过了这一点,我的印象是 View 必须定义自己的 DataContext。谢谢!

标签: wpf xaml mvvm dependency-injection datatemplate


【解决方案1】:

数据模板

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

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

FooView 控件中的this.DataContext = fooViewModel; 行是无用的,因为在这种情况下会覆盖 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 的发起者/生产者,这与模式冲突。

【讨论】:

  • 谢谢@ASh 的工作。我实际上错过了你提到的这一点this.DataContext = fooViewModel; line in FooView control is useless。
猜你喜欢
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
相关资源
最近更新 更多