WPF (MVVM): Closing a view from Viewmodel? WPF (MVVM): Closing a view from Viewmodel? wpf wpf

WPF (MVVM): Closing a view from Viewmodel?


Edit: See my blog post for a more detailed explanation.

When I need to achieve that, I use a IRequestCloseViewModel interface that I created.

This interface contains only one event: RequestClose. This event is raised by the ViewModel (which inherits from a ViewModelBase class AND implement IRequestCloseViewModel) when it wants to close its associated view.

In my app, all Window inherit from an abstract class ApplicationWindow. This abstract class is notified each time the DataContext changed and in the handler checks if the DataContext support the IRequestCloseViewModel. If this is the case, an event handler is set up to close the Window when the event is fired.

Alternatively, like Kent said, you can use screen controller that handle this mecanism in an external class.


Not sure what MVVM framework you are using, but most contain some sort of messaging / notification solution that is easy have things register for messages which are sent. There is no reason that I can imagine that your view could not register for a message such as "CloseWindowsBoundTo" and the viewModel as the sender. Then in your view, you can just register for that message, and compare your current datacontext to the sender. If they match, close the window.

Simple, and keeps your view abstracted from your viewmodel.

Here would be my approach using MVVM-light toolkit:

In the ViewModel:

public void notifyWindowToClose(){    Messenger.Default.Send<NotificationMessage>(        new NotificationMessage(this, "CloseWindowsBoundToMe")    );}

And in the View:

Messenger.Default.Register<NotificationMessage>(this, (nm) =>{    if (nm.Notification == "CloseWindowsBoundToMe")    {        if (nm.Sender == this.DataContext)            this.Close();    }});


I used to use the dialogcloser attached behavior, but i find the below solution easier where I can use it. The sample below takes an example of a close button on the window for simplicity.

pass the window as the command parameter.

in the button xaml for the view:

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"

in the command execute method in the view model:

if (parameter is System.Windows.Window){    (parameter as System.Windows.Window).Close();}