退出应用程序或关闭控件时使用MVVM模式
退出应用程序或关闭控件时使用MVVM模式
在我的WPF应用程序中,我在没有IoC的情况下使用了ViewModelLocator。我通过一个与“关闭窗口命令”相关联的自定义按钮调用了MVVM-Light框架提供的静态ViewModelLocator.Cleanup()方法。这个命令调用了静态ViewModelLocator.Cleanup(),它在我的MainWindowViewModel实例上调用了一个实例Cleanup()方法。然后,实例Cleanup()方法将MainWindow绑定其DataContext的属性设置为null。属性的setter引发了一个PropertyChanged事件。奇怪的是,将该属性设置为null并不会导致窗口关闭。
我试图理解为什么会这样?如果我将MainWindow的DataContext设置为null,那不应该和Window.Close()是一样的吗?在我的情况下,窗口及其所有元素仍然显示在屏幕上。然而,如果我尝试进一步操作,我会得到空指针异常,这表明DataContext绑定属性确实被设置为null;这在调试器中也得到了确认。
我通过钩住Application.Exit事件并在事件处理程序中发出Window.Close()来创建了一个解决方法,以便为我的自定义“关闭窗口”按钮创建相同的功能(即,为了创建与单击窗口右上角的X按钮相同的功能)。由于直接从MVVM调用UI元素(即Window实例)不符合MVVM的友好性,我使用了一个ViewService来实现Window.Close()功能,以保持解决方法与MVVM的友好性。我非常喜欢ViewService的惯用法(或模式),但我认为在这里它不应该是必要的;除非,我可以看到退出应用程序是一个特殊情况,可能应该与应用程序生命周期相关联,而且.Net似乎只允许通过发出Window.Close()方法来退出WPF应用程序。
感谢您的思考。
在使用MVVM模式时,有时候会遇到退出应用程序或关闭控件的问题。下面的内容提供了解决这个问题的原因和方法。
首先,原始问题的答案是,关闭窗口的正确方法类似于我在“解决方法”中描述的方法。关闭应用程序是一个由视图发起的过程,因为窗口控件具有如何关闭的相关信息。当然,你可以挂钩Application.Exit事件,以便在关闭应用程序时对你的ViewModel进行清理、提示用户保存数据等。
在与flq的评论讨论中,我提出了一个问题,即如果我不仅仅将控件的DataContext(即ViewModel)设置为null以释放View和ViewModel资源,我应该如何做呢?
可以在这里找到一个有趣的讨论,并且还有一些细微之处,但基本答案是找到父控件,然后从其Children列表中移除要关闭的控件。注意,这是一种不同的技术和目标,与仅通过将其Visibility属性设置为Collapsed使控件不可见不同。在下面的示例中,"this"是要移除的控件(即"Closed"):
Panel p = (Panel)this.Parent;
p.Children.Remove(this);
我不确定是否还需要将子控件(即"this")设置为null以重新获取其资源,或者仅仅将其从可视树中移除将导致WPF重新获取资源;上述链接的讨论中没有提到这一点。正如原始讨论中提到的,上述技术可以通过挂钩到特定事件或使用其他应用程序特定的逻辑来补充。