WPF项目使用Prism 8.1实现IDialogWindow触发KeyNotFoundException问题咨询
问题原因
- 接口实现错误:混淆了
IDialogWindow和IDialogAware的适用场景。IDialogWindow是给对话框外壳窗体实现的,你的MyDialogWindow已经正确实现了该接口;但对话框的ViewModel应该实现IDialogAware接口而非IDialogWindow,当前MyDialogWindowViewModel实现了错误的接口,属于无效逻辑。 - 注册与调用逻辑混淆:
RegisterDialogWindow<T>()的作用是注册自定义的对话框外壳窗体,而非注册具体要显示的对话框内容,你给该方法传的名称是外壳的命名标识,不是对话框内容的标识。IDialogService.ShowDialog()的第一个入参是你注册的具体对话框内容的名称,不是自定义对话框外壳的名称,你当前传了MyDialogWindow(外壳名),Prism找不到对应注册的对话框内容,就会抛出找不到注册类型的异常。
- 缺少对话框内容注册:没有用
RegisterDialog方法注册要显示的对话框内容(包含实现了IDialogAware的ViewModel和对应的视图)。
解决方案
- 修正ViewModel的接口实现
把MyDialogWindowViewModel改为实现IDialogAware接口,移除所有IDialogWindow相关的实现代码,示例:
public class MyDialogWindowViewModel : IDialogAware { public string Title => "自定义对话框"; public event Action<IDialogResult> RequestClose; public bool CanCloseDialog() => true; public void OnDialogClosed() { // 对话框关闭时的业务逻辑 } public void OnDialogOpened(IDialogParameters parameters) { // 对话框打开时的业务逻辑 } // 按需添加关闭命令、绑定属性等逻辑 }
- 修正注册逻辑
在App.xaml.cs的RegisterTypes方法里,补充注册对话框内容,如果要指定使用自定义的MyDialogWindow作为外壳,就传入对应windowName参数:
protected override void RegisterTypes(IContainerRegistry containerRegistry) { // 注册自定义对话框外壳 containerRegistry.RegisterDialogWindow<MyDialogWindow>(nameof(MyDialogWindow)); // 注册具体的对话框内容,指定使用上面注册的自定义外壳 containerRegistry.RegisterDialog<MyDialogWindow, MyDialogWindowViewModel>("MyCustomDialog", nameof(MyDialogWindow)); }
可选优化:如果你希望所有对话框都默认使用
MyDialogWindow作为外壳,可以去掉RegisterDialogWindow的name参数,注册时写成containerRegistry.RegisterDialogWindow<MyDialogWindow>(),后续注册对话框时不需要再指定windowName参数。
- 修正对话框调用代码
在MainWindowViewModel里调用ShowDialog时,传入你注册的对话框内容的名称,而非外壳的名称:
public MainWindowViewModel(IDialogService dialogService, IRegionManager regionManager) { _dialogService = dialogService; _regionManager = regionManager; // 传入注册的对话框内容名称,而非自定义DialogWindow的名称 _dialogService.ShowDialog("MyCustomDialog"); }
内容的提问来源于stack exchange,提问作者UFO
相关产品推荐
相关产品推荐

