Closing a window in WPF MVVM
I have been working on a project with WPF and MVVM for a while now. In part of my project, I used the following code to close the window. However the code works, but I don't understand the logic of the code yet. My code:
App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView).FirstOrDefault()
.Close();
Why is FirstOrDefault () required?
source to share
It just uses some Linq extensions IEnumerable<T>
to get the first item from the collection that matches the given type and then calls Close
on that instance. This is actually uselessly verbose because it is:
App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView)
is more or less equivalent to this:
App.Current.Windows.OfType<DisplayView>()
Also, a call FirstOrDefault()
followed by "Close" is a bit silly. FirstOrDefault is similar First
, except that it returns null instead of throwing an exception if there are no items, but it throws an exception anyway because you are calling Close on a null object.
So I would write it like this:
App.Current.Windows.OfType<DisplayView>().First().Close();
If you want to check that there is actually a DisplayView instance and prevent an exception in that case, you can use this:
var displayViews = App.Current.Windows.OfType<DisplayView>();
if (displayViews.Any())
displayViews.First().Close();
source to share
Let's break it down:
-
App.Current
: get the current WPF app (must beApplication.Current
my guess) -
.Windows.Cast<Window>()
: get a list of windows, but since this is an untyped collection it is heavily typed to use all LINQ operators -
.Where(win => win is DisplayView)
: LINQ operator to filter the list of windows and keep only those specifiedDisplayView
-
.FirstOrDefault()
: get the first element of this collection, ornull
if not -
.Close()
: close the window we got, it is dangerous as it will blow with helpNullReferenceException
if none is found.
Here's a safer approach:
DisplayView view = App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView)
.FirstOrDefault();
if (view != null)
{
view.Close();
}
source to share