wpf - 使用 WPF Prism / Mahapps HamburgerMenu 控件时调用参数化视图模型构造函数
问题描述
为试图获取尽可能多的信息而发表的长篇文章道歉。我正在使用 WPF (.NET Framework 4.8)、Prism 7、Prism.Unity 和 MahApps。几乎我所有的视图模型都需要参数化构造函数(注入依赖项)。我正在使用内置的 Prism ViewModelLocator.AutoWireViewModel 来连接视图模型(即 prism:ViewModelLocator.AutoWireViewModel="True")。一切正常,但这意味着创建了两个视图模型实例,一次是使用 AutoWireViewModel,另一次是在幕后调用参数化构造函数(请参阅 Brian Lagunas 的评论避免棱镜 AutoWireViewModel 创建 ViewModel 两次)。因此,我将 AutoWireViewModel 值设置为 False,现在在每个视图后面的代码中创建视图模型。我能够在创建视图模型时将所需的依赖项注入到视图构造函数中——这也可以正常工作。我遇到的问题是当我尝试使用 Mahapps HamburgerMenu 控件时。这包含每个子视图的菜单项。据我所知,每个子视图都需要一个无参数构造函数,但我需要一个参数化视图构造函数(注入创建/调用视图模型构造函数所需的依赖项)。我收到的异常/内部异常是:
“在 'MyCompany.Wpf.Modules.Admin.Views.AdminDataGrid' 类型上找不到匹配的构造函数。您可以使用 Arguments 或 FactoryMethod 指令来构造此类型。” 行号'236'和行位置'34'。” “找不到类型‘MyCompany.Wpf.Modules.Admin.Views.AdminDataGrid’的默认构造函数。您可以使用 Arguments 或 FactoryMethod 指令来构造此类型。”
如果我在 AdminDataGrid 视图中添加无参数构造函数,则不会出现错误,但我无法创建视图模型并传递依赖项。
我的代码如下:
包含 HamburgerMenu 的 AdminMainView 代码(问题子视图名为 AdminDataGrid):
<Controls:HamburgerMenu x:Name="HamburgerMenuControl"
HamburgerWidth="48"
IsPaneOpen="True"
CanResizeOpenPane="True"
ItemInvoked="HamburgerMenuControl_OnItemInvoked"
ItemTemplate="{StaticResource MenuItemTemplate}"
OptionsItemTemplate="{StaticResource MenuItemTemplate}"
SelectedIndex="0"
Style="{StaticResource MahApps.Styles.HamburgerMenu.Ripple}"
VerticalScrollBarOnLeftSide="False">
<!-- Items -->
<Controls:HamburgerMenu.ItemsSource>
<Controls:HamburgerMenuItemCollection>
<Controls:HamburgerMenuIconItem Icon="{iconPacks:FontAwesome Kind=TableSolid}" Label="Data Grid">
<Controls:HamburgerMenuIconItem.Tag>
<views:AdminDataGrid />
</Controls:HamburgerMenuIconItem.Tag>
</Controls:HamburgerMenuIconItem>
</Controls:HamburgerMenuItemCollection>
</Controls:HamburgerMenu.ItemsSource>
AdminDataGrid 视图的代码。第二个构造函数是我想调用的: public partial class AdminDataGrid : UserControl, IAdminDataGrid { // 我必须添加它来获取构建/运行的代码。公共 AdminDataGrid() { InitializeComponent(); }
// This is the constructor I would like to call
public AdminDataGrid(ICustomerService service)
{
InitializeComponent();
this.DataContext = new AdminDataGridViewModel(service);
}
}
AdminDataGridViewModel:
public class AdminDataGridViewModel : BindableBase, IAdminDataGridViewModel
{
private ObservableCollection<Customer> _customers;
public ObservableCollection<Customer> Customers
{
get => this._customers;
set => SetProperty(ref _customers, value);
}
public AdminDataGridViewModel(ICustomerService service)
{
Customers = new ObservableCollection<Customer>();
Customers.AddRange(service.GetAllCustomers().OrderBy(c => c.LastName));
}
}
我已经尝试为 AdminDataGrid/AdminDataGridViewModel 创建接口,并且类从它们继承,模块管理器代码是:
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IAdminDataGrid, AdminDataGrid>();
containerRegistry.Register<IAdminDataGridViewModel, AdminDataGridViewModel>();
}
后面的 AdminMainView 代码。注意:我注入 IAdminDataGridViewModel 对象并将其作为 AdminMainViewModel 上的属性公开(想法是将 DataContext 设置为视图的此属性:AdminDataGrid 菜单项 - 但不确定如何或是否可行)。
public AdminMainView(IAdminDataGridViewModel adminDataGridViewModel)
{
this.InitializeComponent();
this.DataContext = new AdminMainViewModel(adminDataGridViewModel);
}
AdminMainViewModel 构造函数:
public AdminMainViewModel(IAdminDataGridViewModel adminDataGridViewModel)
{
this.AdminDataGridViewModel = adminDataGridViewModel;
}
当呈现视图时,如何让 HamburgerMenu 控件使用参数化构造函数:AdminDataGrid 项?谢谢。
解决方案
当呈现视图时,如何让 HamburgerMenu 控件使用参数化构造函数:AdminDataGrid 项?
你不会的。控件应该具有无参数的构造函数,这就是ViewModelLocator
为了规避而发明的。
我只是使用它来创建视图模型(将所有必需的依赖项作为构造函数参数),而不是手动创建和分配数据上下文。
话虽如此,也可以选择先查看模型,而且大多数情况下最好先查看模型。
推荐阅读
- api - 如何获取喜欢推文的用户列表?
- java - 无法以可编辑模式获取数据以使用 jsf 进行更新
- angular - 将参数从 ionic 应用程序传递到外部 html 页面
- c# - Microsoft Graph 如何通过多租户应用注册访问客户端目录
- git - 我可以一次执行多少次 git 提取而不引起问题?
- php - PHP:Instgarm 重定向我的链接检测到不安全
- jquery - 一段时间后跳转到下一页 JQuery
- angular - Angular 7 在上午 09:41 开始一个函数
- vue.js - Vue test-utils 如何使用 vuetify 测试导航栏按钮
- c# - 在我和 pin xamarin 表单之间获取分钟