0

在我的 WPF 应用程序中,我使用的是ViewModelLocator无 IoC。我正在ViewModelLocator.Cleanup()从我自己的按钮调用 MVVM-Light 框架提供的静态方法,该按钮与“关闭窗口命令”相关联。此命令调用 static ViewModelLocator.Cleanup(),它调用我的 MainWindowViewModel 实例上的实例 Cleanup() 方法。然后,实例 Cleanup() 方法将 MainWindow 绑定到的属性设置DataContext为 null。属性的 setter 引发了一个PropertyChanged事件。奇怪的是,将此属性设置为 null 不会导致窗口关闭。

我试图理解为什么会这样?如果我将 MainWindow's 设置DataContext为 null,那应该不一样Window.Close()吗?就我而言,Window 及其所有元素都保留在屏幕上。但是,如果我尝试进一步的操作,我会得到空指针异常,表明DataContext绑定属性确实已设置为空;这在调试器中也得到了证实。

我通过挂钩 Application.Exit 事件并在事件处理程序中发出 Window.Close() 创建了一种解决方法,以便创建我自己的“关闭窗口”按钮(即,为我自己的按钮/命令创建与单击相同的功能窗口右上角的 X 按钮)。由于直接从 MVVM 调用 UI 元素(即 Window 实例)对 MVVM 不友好,因此我使用ViewService来实现 Window.Close() 功能以保持变通方法 MVVM 友好。我是 ViewService 成语(或模式)的忠实拥护者,但我认为这里没有必要;除了,我可以看到退出应用程序是一种特殊情况,它可能应该与应用程序生命周期相关联,而.Net 似乎只允许通过发出 Window.Close() 方法来退出 WPF 应用程序。

想法赞赏。

4

1 回答 1

1

除了我在与 flq 的评论讨论中提出的问题之外,我相信我已经找到了原始问题的答案。

首先,原始问题的答案是关闭窗口的正确方法是按照我在描述的“解决方法”中所做的。关闭应用程序是一个视图启动的过程,因为它是 Window 控件,它具有如何执行此操作的位。您当然可以挂钩 Application.Exit 事件,以便您可以对 ViewModel 执行清理,提示用户保存数据等。

在与 flq 进行一些有趣的讨论后,我提出的问题是,如果我不只是将控件DataContext(即 ViewModel)设置为 null 以释放 View 和 ViewModel 资源,我应该怎么做?

可以在这里找到一个带有一些细微差别的有趣讨论,但基本答案是您找到父控件并从其子列表中删除要关闭的控件。请注意,这是一种不同的技术,其目标不同于通过将 Visibility 属性设置为 Collapsed 来使控件不可见。在以下示例中,“this”是要删除的控件(即“Closed”):

Panel p = (Panel) this.Parent;
p.Children.Remove(this);

我不确定您是否仍需要将子项(即“this”)设置为 null 以重新声明其资源,或者,如果只是从可视化树中删除它会导致 WPF 重新声明资源;上面的链接讨论没有提及。正如在最初的讨论中提到的,上述技术可以通过将其连接到某些事件或使用其他特定于应用程序的逻辑来补充。

于 2012-03-10T20:55:02.953 回答