Separation of concerns is a key principle in object oriented software design. For GUI applications the separated presentation patterns help you separate your View, Model and interaction logic. Personally I’m a big fan of the Model-View-ViewModel for Silverlight and WPF applications as it enables heavy use of data binding. However, in some cases it is useful to combine the MVVM pattern with other members of the separated presentation family of patterns.
I’ve done a fair bit of blogging about the Model-View-ViewModel pattern in a Silverlight 2 context and gotten some good feedback on that. One of the questions I get asked often is how to implement scenarios like multi page navigation, or complex user interactions like and drag and drop within a Model-View-ViewModel context. It turns out that in many cases the problem is that the developer is so focused on implementing the pattern that they fail to see alternative approaches to solve their problems. I’m as guilty of this as anyone – once you get a new hammer everything becomes a nail.
The Model-View-ViewModel belongs to a family of software patterns commonly referred to as separated presentation patterns. These are patterns that try to clearly separate the different concerns of your GUI application. In most cases they separate the View (user interface), the Model (domain and/or data model) and “something else”, which in many cases is the main different between these patterns. Model-View-Controller is one; perhaps the original separated presentation pattern, which has gotten a lot of attention lately as it is proven to be very effective in web development. The popular Ruby on Rails framework is based on this pattern, and Microsoft just released a beta of their ASP.NET MVC framework implementation. The stateless request-response nature of the web makes the MVC pattern a good fit for web applications. You may have a front controller routing an incoming web request to the correct Controller, which in turn makes a decision on what to do. The Controller may fetch some data from the Model and pass it onto a View which will render the HTML.
Another popular pattern is the Model-View-Presenter, which comes in two flavors; Passive View and Supervising Controller. This pattern has many applications and implementations. The Passive View is about reducing the View to a dumb slave driven by the Controller. The View implements a finely grained interface, with properties and methods like Name, Age, Address, without any references to UI framework specific types. The Controller drives the View by setting these properties. The benefit of this approach is that the Controller becomes highly testable, and you can reuse the same Controller in different UI environments. You may implement the View interface for different UI platforms, like web, a Windows client or even a mobile device. The drawback of the Passive View is that you may not leverage the power of the UI platform you are targeting, for instance by using data binding if you’re targeting WPF or Silverlight.
The Supervising Controller flavor of MVP lets the View deal with simple synchronization and mapping against the Model. User input and complex view logic is handled by a Supervising Controller class. This lets you leverage some of the capabilities of the UI platform by accessing the Model directly, while keeping complex code that needs unit tests in a separate class. Later I will show this pattern can be combined with the Model-View-ViewModel pattern to implement drag-and-drop behavior in a WPF application.
Flickr Uploader Sample Application
To show how the Supervising Controller and the Model-View-ViewModel pattern can be combined I’m going to create facetious Flickr Photo Uploading application. I’m not going to implement any real integration with Flickr, but rather focus on how to implement drag-and-drop of photos to upload and how this fits in with the MVVM and Supervising Controller patterns. I picked this sample because I was faced with this exact problem earlier this week on one of the projects I’m working on. It’s a WPF application where we’re using the MVVM pattern for most of it. One of the requirements of the application was support for drag-and-drop import of files from client’s computer. It was not entirely obvious how to implement this in a true MVVM way, and it turned out the addition of a Supervising Controller was a good solution this time.
I’m not going to spend too much time covering the Model-View-ViewModel pattern in depth as I have already done that earlier. I would also recommend checking out Nikhil Kothari and John Gossmans blog posts for more information about the Model-View-ViewModel pattern. However, I will briefly touch on the key concepts of the pattern. The ViewModel part of the pattern is a View-specific class that supports data binding. Each View gets its DataContext property set to an instance of a ViewModel. The different UI elements in the View are data bound to properties on the ViewModel class. The ViewModel notifies the View of any changes by implementing the INotifyPropertyChanged interface and fire the PropertyChanged event whenever the underlying Model changes, or by using an ObservableCollection<T> for collections of data. The View interacts with the ViewModel by executing Commands. For instance clicking the Submit Photos button will execute the SubmitPhotos Command, which will push data back to the underlying Model. The following illustration shows a screenshot of the sample application, and a diagram of how the MVVM pattern is implemented.
The next piece of functionality that needs to be implemented is drag-and-drop. I want to be able to drag files from my hard drive and onto the application. To implement this I need to handle the DragOver and Drop events on my MainWindow class. In my implementation of the MVVM pattern my View holds a reference to the ViewModel, but the ViewModel does not reference the View. So there is no obvious way for my ViewModel to handle these events. I could extend my ViewModel and add a property to give the ViewModel a reference to the View consuming it. I’m not sure if this is a good idea, or if this functionality should be handled by the ViewModel in the first place. Instead I decide to use a Supervising Controller to implement this functionality. The Supervising Controller class accepts the View to control in its constructor. Instead of taking a dependency on the concrete View class I implement a simple IDragDropSurface interface, which has the DragOver and Drop events. The Supervising Controller is created in the View constructor.
The Supervising Controller is responsible for listening to the DragOver and Drop events. When the Drop event executes the Supervising Controller will execute the Import Photos command. This enables the Supervising Controller to communicate with the ViewModel in a loosely coupled way. The ViewModel is responsible for iterating over the list of files and creating FileInfo objects that gets added to the ObservableCollection of FileInfo objects. The View is data bound to this collection and the ItemsControl data template will display the imported photos.
This is an updated diagram showing how the Supervising Controller relates to the view and the View Model.
Summary
Applying separated presentation patterns in your GUI applications is a great way to achieve separation of concerns, decoupling of components and higher level of testability. In this blog post you’ve seen how the Supervising Controller pattern can be combined with a Model-View-ViewModel pattern to implement drag-and-drop functionality. The specific example uses WPF, but the same concepts apply for Silverlight 2 applications as well.