Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Closing View from ViewModel

0.00/5 (No votes)
27 Feb 2013 1  
Lightweight approach to close view from viewmodel command.

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:

  1. Using Attached Behavior
  2. Using Application level service/controller to manage application life cycle
  3. 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).

  1. Create an ICloseable interface that defines the RequestClose event. The ViewModel should implement the ICloseable interface if it supports Closeable behavior.
  2. interface ICloseable
    {
       event EventHandler<EventArgs> RequestClose;
    }
  3. Implement ICloseable in the view model.
  4. class MainWindowViewModel : ViewModelBase, ICloseable 
  5. Add a CloseCommand to the view model.
  6. public ICommand CloseCommand { get; private set; }    
  7. Wire-up a RequestClose event in the Loaded event of the View code behind, if DataContext implements the ICloseable interface.
  8.  Loaded += (s, e) =>
      {
        if (DataContext is ICloseable)
        {
            (DataContext as ICloseable).RequestClose += (_, __) => this.Close();
        }
      }; 
  9. View-viewmodel binding is done in the Application Startup.
  10. protected override void OnStartup(StartupEventArgs e)
    { 
        base.OnStartup(e);
    
        // Create Main Window instance
        MainWindow window = new MainWindow();
    
        // Create Main Window View Model
        MainWindowViewModel viewModel = new MainWindowViewModel();
    
        // Associate DataContext
        window.DataContext = viewModel;
    
        Application.Current.MainWindow = window;
        window.Show();
    }
  11. StartupURI should be removed from MainWindow.xaml.

Points of Interest  

The following refinements are useful:

  1. View view-model binding can be moved from OnStartup to ViewModelLocator.  Refer to this blog for View ViewModel binding approaches.
  2. 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here