我正在将旧的 winforms 程序升级到 WPF,该程序使用 Caliburn Micro 用于 MVVM 和 Ninject 用于 DI。
我已将我的解决方案更新为运行 Caliburn Micro 引导程序的非通用实现的 WPF 解决方案。我这样做是因为我目前没有要运行的基本 ShellViewModel。
我使用的是 Ninject 风格的引导程序,而不是标准的 Caliburn Micro 引导程序,因为我对 Ninject 相当熟悉。
引导程序如下所示:
public class NinjectBootstrapper : Bootstrapper
{
private const string EXTENSION_PATH = "Plugins";
public static IKernel Kernel;
protected override void Configure()
{
Kernel = new StandardKernel();
Kernel.Bind<IEventAggregator>()
.To<EventAggregator>()
.InSingletonScope();
Kernel.Bind<ViewModels.IAnalysisOutputTableViewModel>()
.To<ViewModels.AnalysisOutputTableViewModel>()
.InSingletonScope();
Kernel.Bind<IWindowManager>()
.To<WindowManager>()
.InSingletonScope();
Kernel.Bind<FormMain>()
.ToSelf();
}
protected override object GetInstance(Type serviceType, string key)
{
if (serviceType != null)
{
return Kernel.Get(serviceType);
}
throw new ArgumentNullException("serviceType");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return Kernel.GetAll(service);
}
protected override void BuildUp(object instance)
{
Kernel.Inject(instance);
}
}
为了让我的主窗体启动,我不得不在我的 App.xaml.cs 中重写 OnStartup,如下所示:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
NinjectBootstrapper.Kernel.Get<FormMain>().Show();
}
}
如上所述,我将我的主要 Ninject 内核公开为一个公共静态来访问它,尽管我意识到这可能是一种反模式,一旦我完成了程序的转换,我将解决这个问题。
我已经使用适当的 MVVM 实现了我的主窗体的新子窗口。我需要像这样从按钮打开窗口:
private void dataViewerButton_Click(object sender, EventArgs e)
{
windowManager.ShowWindow(analysisOutputTableViewModel);
}
到目前为止,一切都很好。
问题是当我尝试关闭这个子窗口时。它不仅关闭了窗口,还关闭了我的整个程序。
我想这是因为,由于这个子窗口是 Caliburn 正在处理的唯一窗口(或视图),一旦它被停用,Caliburn 就会为我决定要关闭程序。
有没有办法阻止这种自动关闭行为?也许我应该以不同的方式初始化我的主表单?
更新
使用下面 Marwijn 的回答,我能够正确关闭我的应用程序。
最后,我Application.Exit();
在主窗体的关闭事件中使用了:
private void Form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
Application.Exit();
}
结合对我的 App.xaml.cs 的以下修改:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainForm = NinjectBootstrapper.Kernel.Get<FormMain>();
mainForm.Show();
mainForm.FormClosed += mainForm_FormClosed;
}
void mainForm_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
{
this.Shutdown(0);
}
}
我现在可以使用 Caliburn Micro 和 Ninject 从我的主窗体加载 WPF 窗口,并且一切都正常关闭并且不会留下任何进程运行。在我能够将主窗体更新为 WPF 之前,该解决方案似乎可以正常工作。