Closing View from ViewModel

Introduction 

This short article presents a walk-through to close WPF application from View Model.

Background

Closing/starting a window is UI interaction(owned by view) and should to be decoupled from view model. View model should contain Commands, and Properties (as needed for the view).

View model can also contain events, to which view can respond. In the approach presented in this article, view model event is used to trigger an action owned by view.

There are already multiple approach 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 the article is trimmed down version of above approaches for a small WPF application (where Attached Behavior and Application service are overkill).

Approach    

In this approach, a RequestClose event will be added to ViewModel.   View model will raise RequestClose event and view will respond to it by invoking Close method.

The event wire up and view-viewmodel binding is done in 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 backword compatible. The application uses MVVM Light (for MVVM base framework).

Demo application contains a single window, with a button “Close Me”. Clicking on this button invokes CloseCommand on view model that in-turns raises RequestClose event.  The view handler then closes the instance (on listening RequestClose event).

  1. Create ICloseable interface that defines RequestClose event. ViewModel should implement ICloseable interface if it supportes Closeable behavior.
  2. interface ICloseable
    {
       event EventHandler RequestClose;
    }
    
  3. Implement ICloseable to the view model.
  4. class MainWindowViewModel : ViewModelBase, ICloseable
    
  5. Add CloseCommand to the view model.
  6. public ICommand CloseCommand { get; private set; }
    
  7. Wire-up RequestClose event in the Loaded event of View code behind, if DataContext implementsICloseable interface.
  8. Loaded += (s, e) =>
      {
        if (DataContext is ICloseable)
        {
            (DataContext as ICloseable).RequestClose += (_, __) => this.Close();
        }
      };
    
  9. View-viewmodel binding is done in 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.

Here is attached code. (Rename extension from doc to zip. It is a wordpress limitation)

Points of Interest

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.
Advertisements

About funatlearn

Hi i am a software developer working in noida, india. I have created this blog to jolt down my daily learnings at a single place.

Posted on December 31, 2012, in WPF. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: