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

Wpf 使用MVVM时退出应用程序或关闭控件,wpf,mvvm,user-controls,mvvm-light,viewmodellocator,Wpf,Mvvm,User Controls,Mvvm Light,Viewmodellocator,在我的WPF应用程序中,我使用的是没有IoC的ViewModelLocator。我正在从我自己的按钮调用MVVM Light framework提供的静态ViewModelLocator.Cleanup()方法,该按钮绑定到“关闭窗口命令”。此命令调用静态的ViewModelLocator.Cleanup(),它在我的MainWindowViewModel实例上调用实例Cleanup()方法。然后,instance Cleanup()方法将主窗口绑定其DataContext的属性设置为null。

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

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

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


感谢您的想法。

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

首先,原始问题的答案是,关闭窗口的正确方式与我在所述的“变通方法”中所做的相同。关闭一个应用程序是一个视图启动的过程,因为它是一个窗口控件,它具有如何关闭的位。当然,您可以钩住应用程序。退出事件,以便对ViewModels执行清理、提示用户保存数据等

在与flq进行了一些有趣的讨论之后,我提出的问题是,如果我不只是为了释放视图和视图模型资源而将控件的
DataContext
(即ViewModel)设置为null,我应该如何做

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


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

我不知道你的问题是什么,但通过将其Datacontext设置为null来关闭窗口听起来很不直观,也不是很好useful@flq:您是否同意“关闭”其他视觉元素,与UserControl一样,通常通过将其DataContext绑定到其ViewModel的属性设置为null来完成?我用同样的方法关闭窗口/退出应用程序;似乎是从ViewModel中退出应用程序的正确方法(从而保持MVVM友好)。当然,在适当的清理之后,将Prop设置为null。我想我的问题很简单,如果你想实现你自己的退出按钮,你将如何退出mvvm light应用程序?这种关闭视图的方式是mvvm light特定的行为吗?不是,但经过进一步思考,当数据模板基于数据类型膨胀时,这可能是一种更常见的技术(例如,…)-并随后通过将XyzViewModel设置为null进行调整-而不是将其设置为UserControls或其他控件。仔细想想,这并不是关闭视图。它仍然存在,但在渲染时可能不会占用空间。但是,检查视觉树应该会发现视图仍然存在
Panel p = (Panel) this.Parent;
p.Children.Remove(this);