Prism MVVM:“没有为类型定义无参数构造函数”将 ViewModel 绑定到 View 时出错

Posted

技术标签:

【中文标题】Prism MVVM:“没有为类型定义无参数构造函数”将 ViewModel 绑定到 View 时出错【英文标题】:Prism MVVM: 'No parameterless constructor defined for type' Error when binding ViewModel to View 【发布时间】:2021-04-25 20:22:34 【问题描述】:

我正在创建一个简单的 WPF 应用程序,它有一个单一的视图和视图模型,它在视图模型中为执行计算的服务使用依赖注入。

App.xaml.cs:

public partial class App : Application

   protected override void OnStartup(StartupEventArgs e)
   
      IUnityContainer container = new UnityContainer();
      container.RegisterType<ICharacterCountService, CharacterCountService>();
      container.RegisterType<IMathService, MathService>();
      container.RegisterType<IMainWindowViewModel, MainWindowViewModel>();
      ViewModelLocationProvider.Register<MainWindow, MainWindowViewModel>();
      MainWindow mainWindow = container.Resolve<MainWindow>();
      mainWindow.Show();
   

MainWindow.xaml:

<Window x:Class="MyFirstMVVM.Views.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyFirstMVVM"
           xmlns:prism="http://prismlibrary.com/"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="400"
        prism:ViewModelLocator.AutoWireViewModel="True">

MainWindowViewModel中的构造函数:

public MainWindowViewModel(IMathService mathService, ICharacterCountService characterCountService)

   _mathService = mathService;
   _characterCountService = characterCountService;

   AddCommand = new DelegateCommand(Add);
   CountCommand = new DelegateCommand(Count);

如果您在视图模型中有一个无参数构造函数,您似乎只能使用ViewModelLocator,在这种情况下,我将无法注入CharacterCountServiceMathService。我是否必须使用另一种方法将视图 DataContext 设置为视图模型?

我也尝试过直接在视图中设置DataContext,但出现类似错误:

【问题讨论】:

提供者没有使用容器,因此不知道如何解决依赖关系。提供者需要一个工厂来知道如何解决依赖关系。 【参考方案1】:

当您构建 Prism 应用程序时,您的 App 类应派生自 PrismApplication。它设置了 Prism 所需的所有基础架构,以及您使用的 ViewModelLocator。它会自动将当前容器连接到ViewModelLocationProvider 以解析类型。这意味着,任何具有注册到容器的参数的构造函数都可以毫不费力地工作。

但是,默认情况下,在没有任何初始化的情况下,ViewModelLocationProvider 将使用反射命名空间中的Activator 来实例化如下所示的类型,最终是requires a parameterless constructor。

type => Activator.CreateInstance(type);

因此,您有两种选择可以让它发挥作用。

PrismApplication 派生您的主要应用程序类型App 并正确初始化它。要开始使用,请查看Override the Existing Application Object

自己初始化ViewModelLocationProvider类型工厂。

ViewModelLocationProvider.SetDefaultViewModelFactory((view, type) => container.Resolve(type));

对于 XAML 声明,这与使用无参数构造函数在代码中实例化类型完全相同。由于您没有提供一个,因此您会得到这个错误。

var mainWindowViewModel = new MainWindowViewModel();

【讨论】:

值得注意:每个受支持的容器都有一个 PrismApplication “从 PrismApplication 派生您的主要应用程序类型 App 并正确初始化它。要开始,请查看 Override the Existing Application Object” 这解决了我的问题,谢谢! :)

以上是关于Prism MVVM:“没有为类型定义无参数构造函数”将 ViewModel 绑定到 View 时出错的主要内容,如果未能解决你的问题,请参考以下文章

六从GitHub浏览Prism示例代码的方式入门WPF下的Prism之MVVM中的FilteringEvents

从PRISM开始学WPFMVVMViewModel?

从PRISM开始学WPFMVVMCommand?

Prism/MVVM (MEF/WPF):从模块中公开导航 [例如菜单]

MVVM Prism WPF - 设置公共属性和 SetProperty

.NET Core 3 WPF MVVM框架 Prism系列之导航系统