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

如何在独立类库的Caliburn.Micro ViewModel中关闭WPF应用?

解决ViewModel在独立类库中关闭WPF应用的问题

我之前也碰到过这种ViewModel和WPF项目分离的场景,确实不能直接引用System.Windows.Application,不过借助Caliburn.Micro的特性和依赖注入思想,有几种优雅的解决办法:

方案1:通过依赖注入传递关闭委托

这是最直接的方式,把关闭应用的逻辑封装成委托,从WPF项目注入到ViewModel中,ViewModel只需要调用委托即可,完全不用依赖WPF API。

  1. 在你的ViewModel基类ViewModelBase中添加一个用于关闭应用的委托属性:
public abstract class ViewModelBase : PropertyChangedBase
{
    // 其他已有属性:IoC、窗口管理器、事件聚合器...
    protected Action? ShutdownApp { get; set; }

    // 提供统一调用方法给子类ViewModel
    protected void RequestShutdown()
    {
        ShutdownApp?.Invoke();
    }
}
  1. 在WPF项目的Bootstrapper(比如AppBootstrapper)中,配置依赖注入时赋值这个委托:
public class AppBootstrapper : BootstrapperBase
{
    private SimpleContainer _container;

    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        _container = new SimpleContainer();
        // 注册Caliburn.Micro核心服务
        _container.Singleton<IWindowManager, WindowManager>();
        _container.Singleton<IEventAggregator, EventAggregator>();

        // 注册ViewModel并注入关闭委托
        _container.PerRequest<MainViewModel>(() => 
        {
            var vm = new MainViewModel();
            vm.ShutdownApp = () => System.Windows.Application.Current.Shutdown();
            return vm;
        });
    }

    // 其他Bootstrapper重写方法...
}
  1. 在目标ViewModel中,需要关闭应用时直接调用:
public class MainViewModel : ViewModelBase
{
    public void OnExitButtonClicked()
    {
        RequestShutdown();
    }
}

方案2:使用事件聚合器发布退出事件

这种方式更符合解耦思想,ViewModel只负责发布“需要退出”的事件,WPF项目负责订阅并执行关闭逻辑。

  1. 在ViewModel类库中定义一个空的事件类:
public class RequestApplicationShutdownEvent { }
  1. 在ViewModel中通过IEventAggregator发布事件:
public class MainViewModel : ViewModelBase
{
    private readonly IEventAggregator _eventAggregator;

    public MainViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void OnExitButtonClicked()
    {
        _eventAggregator.PublishOnUIThread(new RequestApplicationShutdownEvent());
    }
}
  1. 在WPF项目的Bootstrapper中订阅并处理事件:
public class AppBootstrapper : BootstrapperBase
{
    private IEventAggregator _eventAggregator;

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        _eventAggregator = IoC.Get<IEventAggregator>();
        _eventAggregator.Subscribe(this);
        DisplayRootViewFor<MainViewModel>();
    }

    // 处理退出事件
    public void Handle(RequestApplicationShutdownEvent message)
    {
        System.Windows.Application.Current.Shutdown();
    }

    // 其他Bootstrapper方法...
}

方案3:定义抽象服务接口

通过抽象接口隔离WPF的具体实现,ViewModel只依赖接口,WPF项目提供实现。

  1. 在ViewModel类库中定义接口:
public interface IApplicationService
{
    void Shutdown();
}
  1. 在ViewModelBase中注入该接口:
public abstract class ViewModelBase : PropertyChangedBase
{
    protected readonly IApplicationService _applicationService;

    protected ViewModelBase(IApplicationService applicationService)
    {
        _applicationService = applicationService;
    }

    protected void RequestShutdown()
    {
        _applicationService.Shutdown();
    }
}
  1. 在WPF项目中实现接口:
public class WpfApplicationService : IApplicationService
{
    public void Shutdown()
    {
        System.Windows.Application.Current.Shutdown();
    }
}
  1. 在Bootstrapper中注册服务:
protected override void Configure()
{
    _container = new SimpleContainer();
    // 注册核心服务...
    _container.Singleton<IApplicationService, WpfApplicationService>();
    // 注册ViewModel...
}

方案4:利用Caliburn.Micro的窗口关闭约定

如果你的退出逻辑就是关闭主窗口(主窗口关闭后WPF默认退出应用),可以直接用Caliburn的约定:ViewModel中定义Close方法,绑定到按钮即可,Caliburn会自动处理窗口关闭。

public class MainViewModel : ViewModelBase
{
    public void Close()
    {
        // 无需写逻辑,Caliburn会自动关闭当前绑定的窗口
    }
}

View中绑定按钮:

<Button Content="退出" cal:Message.Attach="[Event Click] = [Action Close]" />

内容的提问来源于stack exchange,提问作者ZaHaDum1984

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:55:08