You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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):

  1. 注入IWindowManager到ScriptViewModel:
private readonly IWindowManager _windowManager;

[ImportingConstructor]
public ScriptViewModel(IEventAggregator eventAggregator, IWindowManager windowManager)
{
    _eventAggregator = eventAggregator;
    _windowManager = windowManager;
    _eventAggregator.SubscribeOnUIThread(this);
}
  1. 添加打开设置窗口的方法:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:21:36