Introduction
This short article presents a walk-through of
how to close a WPF application from the View Model.
Background
Closing/starting a window is UI interaction (owned by the view) and should be decoupled from
the view model. The view model should contain Commands and Properties (as needed for the view).
View model can also contain events to which the view can respond. In the approach presented in this article,
a view model event is used to trigger an action owned by the view.
There are already multiple approaches to this problem:
- Using
Attached Behavior
- Using Application level service/controller to manage application life cycle
- Using Message Bus (like MVVM Light Messenger/Prism Event Aggregator)
The approach mentioned in this article is a trimmed down version of the above approaches for a small WPF application (where
an Attached Behavior or Application service are overkill).
Approach
In this approach, a RequestClose
event will be added to the ViewModel.
The view model will raise a RequestClose
event and the view will respond
to it by invoking the Close
method.
The event wire up and
the view-viewmodel binding is done in the Application startup override.
Using the Code
The code is written in VS2012 RTM. It should be opened in VS2010/VS2012RTM/VS2012 as
Visual Studio projects / solutions are now backwards compatible.
The application uses MVVM Light (for
an MVVM based framework).
The demo application contains a single window with a button "Close Me". Clicking on this button invokes
a CloseCommand
on the view model that in turn raises a RequestClose
event. The view handler then closes the instance (on listening
to the RequestClose
event).
- Create an
ICloseable
interface that defines the RequestClose
event.
The ViewModel should implement the ICloseable
interface if it supports Closeable behavior. interface ICloseable
{
event EventHandler<EventArgs> RequestClose;
}
- Implement
ICloseable
in the view model.
class MainWindowViewModel : ViewModelBase, ICloseable
- Add a
CloseComm
and
to the view model.
public ICommand CloseCommand { get; private set; }
- Wire-up a
RequestClose
event in the Loaded
event of
the View code behind, if DataContext
implements the ICloseable
interface. Loaded += (s, e) =>
{
if (DataContext is ICloseable)
{
(DataContext as ICloseable).RequestClose += (_, __) => this.Close();
}
};
- View-viewmodel binding is done in the Application
Startup
.
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
MainWindowViewModel viewModel = new MainWindowViewModel();
window.DataContext = viewModel;
Application.Current.MainWindow = window;
window.Show();
}
StartupURI
should be removed from MainWindow.xaml.
Points of Interest
The following refinements are useful:
- View view-model binding can be moved from
OnStartup
to
ViewModelLocator
. Refer to
this blog for View ViewModel binding approaches. - Event wire-up can be refreshed on
DataContext
change notification.
History
This is the second version of the article. In this revision, the ICloseable
interface is introduced and
event wire up for the RequestClose
event has been moved to the View.