使用MVVM时退出应用程序或关闭控件

时间:2012-03-10 15:43:19

标签: wpf mvvm user-controls mvvm-light viewmodellocator

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

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

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

赞赏的想法。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

我不确定您是否仍然需要将子设置(即“this”)设置为null以重新声明其资源,或者,如果仅从可视树中删除它将导致WPF重新声明资源;上述相关讨论没有提及。正如原始discussion中所提到的,上述技术可以通过将其挂钩到某些事件或使用其他特定于应用程序的逻辑来补充。