【问题标题】:Exiting an App or Closing a Control When Using MVVM使用 MVVM 时退出应用程序或关闭控件
【发布时间】:2012-03-10 15:43:18
【问题描述】:

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

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

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

想法表示赞赏。

【问题讨论】:

  • 我不知道你的问题是什么,但是通过将其 Datacontext 设置为 null 来关闭窗口听起来很不直观,也不是很有用
  • @flq:您是否同意“关闭”其他可视元素(如 UserControl)通常通过将其 DataContext 绑定到其 ViewModel 的属性设置为 null 来完成?我采用相同的方法关闭窗口/退出应用程序;似乎是从 ViewModel 退出应用程序的正确方法(从而保持 MVVM 友好)。当然,将 Prop 设置为 null 遵循任何可能适当的清理。我想我的问题很简单,如果您想实现自己的退出按钮,您将如何退出 mvvm-light 应用程序?
  • 这种关闭视图的方式是 MVVM-light-specific 行为吗?
  • 不,但经过进一步思考,当 DataTemplate 基于 DataType(例如,.. .) - 并随后通过将 XyzViewModel 设置为 null 来缩小 - 而不是 UserControls 或其他控件。
  • 如果你仔细想想,这不是关闭视图。它仍然存在,但可能不会占用渲染空间。但是,对可视化树的检查应该会发现视图仍然存在

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


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    • 2011-07-12
    相关资源
    最近更新 更多