Lately I’ve been developing standalone WPF applications using Visual Basic. To make a WPF application somewhat easy to maintain and extend it is extremely important to use some design pattern. The most popular design pattern around when developing WPF applications is the MVVM pattern (Model-View-ViewModel).
Developing a single view application is really really straight forward using the MVVM pattern, but when it comes to multiple views application there is no simple solution to update one or more views from another view and still make the Views and ViewModels behind them loosely coupled. When I say update I mean making some property change in the ViewModels behind the Views to be affected by the change of something in another View or ViewModel.
In this post I will show how I’ve solved the problem using events and delegates. Before I describe my solution, please read about the basics in the MVVM design pattern. There are a lot of good publications around, e.g. THE MODEL-VIEW-VIEWMODEL (MVVM) DESIGN PATTERN FOR WPF and Model View ViewModel (Wikipedia).
To make it easier to understand this post and to make it easier for me to write it, please read the following article if you’re not familiar with WPF data binding and the usage of INotifyPropertyChanged: http://coredotnet.blogspot.com/2006/05/wpf-data-binding-tutorial.html.
The problem
I wanted to implement a small application with two Views, one for displaying an image (MainView) and one for selecting the particular image to display (SelectImageView), using a list filled with images from a certain directory. This seems rather basic, but I want the MainView to display the image as soon as it is selected in the list in the SelectImageView.
The easy way to do this is to make the two Views refer one another but this makes them less loosely coupled. A better solution to this is to make the SelectImageView raise some event when the selection changes. This makes way for other Views and controls to subscribe to this event and the SelectImageView will be unaffected. To make things clear from the beginning it will be the ViewModel behind the SelectImageView, SelectImageViewModel, that raises the event. This is because of the fact that one of the goals with the MVVM pattern is to leave the codebehind files as “code-less” as possible.
The Views
The Views in this little demo application looks like this:

The [Select image] button will open the View with the list of images, while the [Open another MainView] button will open another MainView like the one above. I will maybe explain why I added the [Open another...] button later on.

This SelectImageView will list the images in a certain folder.
The SelectImageView is opened non-modal and the ViewModel behind the View will raise events to possible subscribers when the current selected item in the list changes.
The XAML-code for the Views will be presented after the ViewModels are presented, since the data binding will be much clearer after that.
The ViewModels
A ViewModel behind a View in an MVVM-designed WPF application is in most cases a plain .NET class (C#, VB or whatever language you’re using) exposing a couple of properties to data bind to the controls in the View.
The ViewModels in this case the MainViewModel and SelectImageViewModel classes. I will present the code for SelectImageViewModel (SelectImageViewModel.cs) before the MainViewModel because the SelectImageViewModel is much simpler than the MainViewModel.
SelectImageViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace EventDemoWPF
{
class SelectImageViewModel
{
// The event to be raised.
public event SelectedImageChangedHandler ImageSelectionChanged;
// The delegate to handle the event.
public delegate void SelectedImageChangedHandler(string imageSource);
// FileInfo object array for the images (databound).
// Initialized in the constructor for this class.
public FileInfo[] ImageFiles { get; set; }
private FileInfo _selectedImage;
// The FileInfo currently selected (databound).
public FileInfo SelectedImage
{
get
{
return _selectedImage;
}
set
{
if (value != _selectedImage)
{
// Value changed.
_selectedImage = value;
if (ImageSelectionChanged != null)
{
// There is an active listener for the event,
// so let's raise the event.
ImageSelectionChanged(_selectedImage.FullName);
}
}
}
}
public SelectImageViewModel()
{
// Hardcoded path for demo purpose.
string path = @"C:\develop\Icons\PNG";
// DirectoryInfo object to get the png images.
DirectoryInfo di = new DirectoryInfo(path);
// Fill the FileInfo array
ImageFiles = di.GetFiles("*.png");
}
}
}
Some notes on SelectImageViewModel.cs:
Let’s begin with the really basic stuff, the properties ImageFiles (line 19) and SelectedImage (line 23).
- The ImageFiles is an array of FileInfo objects filled in the constructor for the class. This property is data bound to the ItemsSource property of the ListView control in the XAML-code for the SelectImageView.
- The SelectedImage is the currently selected item in the list of FileInfos. This property is data bound to the SelectedItem property of the ListView control in the XAML-code.
Note that the SelectedImage set method is the one that will be raising the event (on line 40) IF there are any subscribers.
On line 12 and 15 are the event and the delegate declared so that the set method of the SelectedImage will be able to raise an event if needed. If the event would be static the event would be accessible from any class in the context of the application. I will leave the event to be non-static to make it possible for a subscriber of the event to listen to events raised from a specific instance of the SelectImageViewModel class.
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.ComponentModel;
namespace EventDemoWPF
{
class MainViewModel : INotifyPropertyChanged
{
// Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// Help method for raising the PropertyChanged event
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
private string _imageSource;
// The current image source
public string ImageSource
{
get { return _imageSource; }
set {
if (value != _imageSource)
{
// Value changed, raise the NotifyPropertyChanged
_imageSource = value;
NotifyPropertyChanged("ImageSource");
}
}
}
private ICommand _showSelectImageCommand;
// The ICommand instance bound to the button in the view.
public ICommand ShowSelectImageCommand
{
get
{
if (_showSelectImageCommand == null)
// Create an instance, point out the function to be executed.
_showSelectImageCommand = new MyCommandBase(ShowSelectImage);
return _showSelectImageCommand;
}
set
{
_showSelectImageCommand = value;
}
}
private ICommand _openAnotherMainViewCommand;
// The ICommand instance bound to the button in the view.
public ICommand OpenAnotherMainViewCommand
{
get
{
if (_openAnotherMainViewCommand == null)
// Create an instance, point out the function to be executed.
_openAnotherMainViewCommand = new MyCommandBase(OpenAnotherMainView);
return _openAnotherMainViewCommand;
}
set
{
_openAnotherMainViewCommand = value;
}
}
// Show the select image view.
private void ShowSelectImage(object sender)
{
SelectImageViewModel sivm = new SelectImageViewModel();
// Subscribe to the image selection changed event.
sivm.ImageSelectionChanged +=
new SelectImageViewModel.SelectedImageChangedHandler(
SelectImageViewModel_ImageSelectionChanged);
SelectImageView siv = new SelectImageView();
// Bind the view to the viewmodel
siv.DataContext = sivm;
// Show the view modeless
siv.Show();
}
// Open yet another MainView window
private void OpenAnotherMainView(object sender)
{
MainView mv = new MainView();
mv.Show();
}
// Event handler when the image source is changed
// (from external object/view/viewmodel)
void SelectImageViewModel_ImageSelectionChanged(string imageSource)
{
ImageSource = imageSource;
// Write event data to the debug log
System.Diagnostics.Debug.WriteLine(
string.Format("ImageSelectionChanged: {0}", ImageSource));
}
}
}
Some notes on MainViewModel.cs:
As before, let’s begin with the basic stuff, e.g. the properties:
- On line 24 the ImageSource property is declared and implemented. This property is data bound to the Source property on the Image control in the XAML-code for the MainView. When this property is updated it will raise the NotifyPropertyChanged event (see below).
- On line 39 the ShowSelectImageCommand is declared. This is an instance of the interface ICommand (see the note on my implementation of the ICommand interface below). When the Command is invoked from the View the method ShowSelectImage (line 74) is trigged and it will create and show a SelectImageView (line 89) with the data context set to an instance of SelectImageViewModel (line 86).
- On line 57 the OpenAnotherMainViewCommand is declared using the same pattern of implementation as just describe above. The method trigged by this command is OpenAnotherMainView on line 93.
As seen on line 10 and line 13-20 the class implements the INotifyPropertyChanged. In this implementation I added a help method for raising the event, forcing the controls in the View data bound to the given property to update.
If more information is needed about the INotifyPropertyChanged stuff, please consult MSDN or Google, there are a lot of interesting articles on this topic.
The key point
The key point to make this demo application work is the event raised from SelectImageViewModel (on line 40 in the listing for the class above) and the subscription for this event in the MainViewModel (on line 79 in the listing above). The event is raised as soon as the selected FileInfo object changes and there is at least one subscriber of the event. The event is caught in the MainViewModel and handled by SelectImageViewModel_ImageSelectionChanged method. The ImageSource property is updated on line 103, causing a NotifyPropertyChanged event to be raised on line 32 and the data bound control will receive the updated value. The sequence looks as below
- The MainViewModel creates a SelectImageViewModel instance (MainViewModel.cs, line 76).
- The MainViewModel subscribes to the event, receiving updates from the SelectImageViewModel (MainViewModel.cs, line 79).
- An instance of SelectImageView is created and the data context is set to the instance of SelectImageViewModel created above (MainViewModel.cs, line 83 and 86).
- The SelectImageView is shown (MainViewModel.cs, line 89).
- The SelectImageView displays a list of image files and the selected item is bound to the property SelectedImage (SelectImageViewModel.cs, line 23 and 55). The array behind this list is filled in the class c’tor.
- The SelectImageViewModel will raise an event when the selection in the data bound control changes (SelectImageViewModel.cs, line 40).
- The SelectImageViewModel_ImageSelectionChanged is invoked when receiving the event raised above and it updates the ImageSource property (MainViewModel.cs, line 101 and 103).
- The change of the ImageSource property raises a NotifyPropertyChange event, causing the data bound control to update (MainViewModel.cs, line 32), showing the selected image file.
The Views
I will now present the XAML-code for the Views. First out is MainView.xaml (sorry for making it an image, but the syntax highlighter didn’t like the raw XML code):

Notes on MainView.xaml:
- The data context is an instance of the MainViewModel class.
- The Image control source attribute is bound to the ImageSource property in the data context class.
- The Select image button command attribute is bound to the ShowSelectImageCommand property in the data context class.
- The [Open another...] button is there for demo purposes, having two different SelectImage views sending events handled by different MainViewModels (the button will cause the OpenAnotherMainView method to be invoked, opening yet another MainView, line 93-97 in the MainViewModel.cs listing above).
Here goes the SelectImageView.xaml:

Notes on SelectImageView.xaml:
- This view is straight forward, containing a single ListView control with the property ItemsSource bound to the ImageFiles property in the data context class, e.g. an instance of SelectImageViewModel.
- The ImageFiles list is created and filled with FileInfo objects in the c’tor of the data context class.
- The SelectedItem property of the list will change upon selection changes, causing the event to be raised.
Summary
I hope that the above text and code will make it fairly clear what I wanted to accomplish with this post. The key point is to make Views and ViewModels as loosely coupled as possible but still have the possibility to have them exchanging information.
The thing with raising events and catching them in different places is nothing new at all, but I wanted to show a simple example on this. As soon as I have made it possible for me to attach files here, other than media files, I will attach the Visual Studio solution used in this post.
Thanks, It helped me alot. I used static event because my viewmodels are independent and they are not subviews.
Hello Fredde,
Got here from Gabriel’s site — needed the Google Map bounding box thing sorted.
Anyway, it seems as though your coupling is still rather high since you are specifically linking the event.
I have used a slightly different mechanism I borrowed from the ESB world. I use a front-end message bus and objects can subscribe to specific messages they are interested in.
Another trick to avoid having to check for event listeners is to use an empty listener:
public event SelectedImageChangedHandler ImageSelectionChanged = delegate { };
Then you know you always have one
— so now you can just raise the event.
I have an example application utilising many different techniques should you be interested:
http://www.ebenroux.co.za/page/Abacus.aspx
The plan is to extend it to demonstrate various enterprise-level techniques and technologies.
Regards,
Eben