正在关闭WPF MVVM中的窗口

本文关键字:窗口 MVVM WPF | 更新日期: 2023-09-27 18:19:36

我已经用WPF和MVVM做了一段时间的项目。在我项目的一部分中,我使用以下代码关闭了一个窗口。代码是有效的,但是,我还不理解代码背后的逻辑。我的代码是:

App.Current.Windows.Cast<Window>()
    .Where(win => win is DisplayView).FirstOrDefault()
    .Close();

为什么需要FirstOrDefault()?

正在关闭WPF MVVM中的窗口

它只使用一些Linq IEnumerable<T>扩展从与给定类型匹配的集合中获取第一个项,然后在该实例上调用Close。它实际上是不必要的冗长,因为这是:

App.Current.Windows.Cast<Window>()
    .Where(win => win is DisplayView)

或多或少相当于:

App.Current.Windows.OfType<DisplayView>()

另外,在调用FirstOrDefault()之后再调用"Close"有点傻。FirstOrDefault类似于First,只是如果没有元素,它会返回null而不是抛出异常——但在这种情况下,它无论如何都会抛出异常,因为您将对null对象调用"Close"。


所以我会这样写:

App.Current.Windows.OfType<DisplayView>().First().Close();

如果您想验证是否确实存在DisplayView实例,并在这种情况下防止异常,那么您可以使用以下方法:

var displayViews = App.Current.Windows.OfType<DisplayView>();
if (displayViews.Any())
    displayViews.First().Close();

让我们拆分一下:

  • App.Current:获取正在运行的WPF应用程序(我认为应该是Application.Current
  • .Windows.Cast<Window>():获取窗口列表,但由于这是一个非类型化的集合,请将其强类型化以使用所有LINQ运算符
  • .Where(win => win is DisplayView):LINQ运算符过滤窗口列表,只保留DisplayView类型的窗口列表
  • .FirstOrDefault():获取此集合的第一个元素,如果没有,则获取null
  • .Close():关上我们得到的窗户,这很危险,因为如果没有找到NullReferenceException,它会被吹走

这里有一个更安全的方法:

DisplayView view = App.Current.Windows.Cast<Window>()
                                      .Where(win => win is DisplayView)
                                      .FirstOrDefault();
if (view != null)
{
    view.Close();
}