Caliburn.Micro 4.0.173弹窗传参失败:EventAggregator订阅无响应求助
Caliburn.Micro ViewModel间参数传递问题解决
先修复代码中的致命错误
你的SettingViewModel构造函数存在笔误,把类名写成了ItemViewModel,导致依赖注入无法正确注入IEventAggregator,这是事件无法被接收的核心原因之一:
// 错误写法 public ItemViewModel(IEventAggregator eventAggregator) { _eventAggregator = eventAggregator; } // 正确写法 public SettingViewModel(IEventAggregator eventAggregator) { _eventAggregator = eventAggregator; }
确保EventAggregator实例一致
Caliburn.Micro的IEventAggregator必须是单例实例才能保证发布和订阅的是同一个事件总线。如果使用MEF(Caliburn.Micro默认容器),需要确保IEventAggregator的导出是单例:
[Export(typeof(IEventAggregator))] [PartCreationPolicy(CreationPolicy.Shared)] public class EventAggregator : Caliburn.Micro.EventAggregator, IEventAggregator { }
如果用其他容器(比如Autofac),也要配置IEventAggregator为单例模式。
正确弹出SettingViewModel
在ScriptViewModel中,需要通过IWindowManager正确弹出SettingViewModel,确保其实例由容器创建(从而获取正确的IEventAggregator):
- 注入
IWindowManager到ScriptViewModel:
private readonly IWindowManager _windowManager; [ImportingConstructor] public ScriptViewModel(IEventAggregator eventAggregator, IWindowManager windowManager) { _eventAggregator = eventAggregator; _windowManager = windowManager; _eventAggregator.SubscribeOnUIThread(this); }
- 添加打开设置窗口的方法:
public void OpenSettingWindow() { var settingVm = IoC.Get<SettingViewModel>(); _windowManager.ShowDialog(settingVm); }
通过IoC.Get<>获取容器中的实例,确保依赖注入生效。
验证事件接收
修复以上问题后,测试BtnSaveItem方法触发的事件应该能被ScriptViewModel的Handle方法接收。你可以在Handle中添加日志或断点验证:
public void Handle(FooEvent fooEvent) { // 这里可以接收参数并处理 var receivedValue = fooEvent.Foo; // 示例:更新ScriptViewModel中的属性 NotifyOfPropertyChange(() => SomeProperty); }
其他可选参数传递方案
如果EventAggregator方式仍有问题,还可以用更直接的回调方式:
方案1:通过回调方法传递参数
在SettingViewModel中定义一个回调委托,保存时调用:
public class SettingViewModel : Screen { public Action<bool> OnSaveCallback { get; set; } public void BtnSaveItem() { bool settingValue = true; // 这里替换为你的实际参数 OnSaveCallback?.Invoke(settingValue); TryClose(); // 关闭窗口 } }
在ScriptViewModel中打开窗口时设置回调:
public void OpenSettingWindow() { var settingVm = IoC.Get<SettingViewModel>(); settingVm.OnSaveCallback = (value) => { // 处理接收的参数 }; _windowManager.ShowDialog(settingVm); }
方案2:通过ViewModel属性传递
利用ShowDialog的返回值,结合SettingViewModel的公开属性:
// SettingViewModel中添加公开属性 public bool SettingValue { get; set; } public void BtnSaveItem() { SettingValue = true; // 设置参数 TryClose(true); // 返回DialogResult为true }
在ScriptViewModel中接收:
public void OpenSettingWindow() { var settingVm = IoC.Get<SettingViewModel>(); if (_windowManager.ShowDialog(settingVm) == true) { var receivedValue = settingVm.SettingValue; // 处理参数 } }
内容的提问来源于stack exchange,提问作者Ben Pai
相关产品推荐
相关产品推荐

