使用 MVVM 时退出应用程序或关闭控件 [英] Exiting an App or Closing a Control When Using MVVM

查看:25
本文介绍了使用 MVVM 时退出应用程序或关闭控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my WPF application, I am using the ViewModelLocator without IoC. I am calling the static ViewModelLocator.Cleanup() method provided by the MVVM-Light framework from my own button which is tied to a "close window command". This Command calls the static ViewModelLocator.Cleanup(), which calls an instance Cleanup() method on my MainWindowViewModel instance. The instance Cleanup() method then sets the property to which the MainWindow binds its DataContext, to null. The setter on the property raises a PropertyChanged event. Curiously, setting this property to null does not cause the window to close.

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

I am trying to understand why this is the case? If I set the MainWindow's DataContext to null, should that not be the same as Window.Close()? In my case, the Window and all of its elements remain on the screen. However, if I attempt further actions, I get null pointer exceptions, indicating the DataContext binding Property has indeed been set to null; this has also been confirmed in the debugger.

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

I have created a workaround by hooking the Application.Exit event and issuing a Window.Close() in the event handler in order to create my own "Close Window" button (ie, to create same functionality for my own Button / Command as clicking the X button in the upper right of a Window). Since calling a UI element (ie, the Window instance) from MVVM directly is not MVVM friendly, I used a ViewService to implement the Window.Close() functionality in order to keep the workaround MVVM friendly. I am a big fan of the ViewService idiom (or pattern), but I just don't think it should be necessary here; except, I could see how exiting the app is a special case that perhaps should tie-in with the application lifecycle, and .Net seems to only allow exiting a WPF app by issuing the Window.Close() method.

想法表示赞赏.

推荐答案

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

I believe I have found the answer to my original question, in addition to the one raised in my comments discussion with flq.

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

First, the answer to the original question is that the proper way to close the Window is along the lines of what I did in my described "workaround". Closing an app is a View-initiated process, as it is the Window control that has the bits for how to do it. You can of course hook the Application.Exit event so that you can perform cleanup on your ViewModels, prompt the user to save data, etc..

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

The question raised by me after some interesting discussion with flq is, if I don't just set a control's DataContext (ie, ViewModel) to null in order to release the View and ViewModel resources, how should I do it?

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

An interesting discussion with some nuances can be found here, but the basic answer is that you find the parent control and remove the control you want to close from its Children list. Note, this is a different technique with a different goal than just making the control not visible by setting is Visibility property to Collapsed. In the following example, "this" is the control to be removed (ie, "Closed"):

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

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

I am not sure if you still need to then set the child (ie, "this") to null to re-claim its resources, or, if just removing it from the visual tree will cause WPF to re-claim the resources; the above linked discussion makes no mention. As mentioned in the original discussion, the above technique can be supplemented by hooking it to certain events, or using other application specific logic.

这篇关于使用 MVVM 时退出应用程序或关闭控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆