Mediator v2 for MVVM WPF and Silverlight applications

This last 2 weeks, us WPF Disciples have been talking a lot about the Mediator pattern for MVVM applications. Me and Josh Smith revised my previous Mediator implementation and found some problems with it.

Problem: There was a memory leak. Once a Mediator subscribes for one or more messages it would be kept in memory since the Mediator was holding a reference to the ViewModel.
Solution: We could have just exposed an unregister method so that when you call this method the Mediator would release the instance of the ViewModel. But sometimes it is hard to know when a ViewModel is going to die… So we went a step further and created the WeakAction. The WeakAction stores the instance of the ViewModel in a WeakRefence thus the ViewModel can be garbage collected without any problem and once it does get garbage collected the Mediator automatically removes that ViewModel registration from the list.

While we were at it we PIMPED the Mediator API :) We added 2 approaches to subscribe to the Mediator and we also added support for (thanks to David Anson suggestion) strongly typed parameters.

So now the Mediator offers 2 methods of registration, a declarative way of registering and an imperative way as well.

The Declarative approach. (Supported in WPF and Silverlight)

This approach uses attributes so that you can decorate the messages that act as subscribers for messages.Here is an example

   1: /// <summary>

   2: /// Subscribe to Message1

   3: /// </summary>

   4: /// <param name="message">The message to be passed</param>

   5: [MediatorMessageSink(MediatorMessages.Message1, ParameterType = typeof(SomeData))]

   6: public void Test(SomeData data)

   7: {

   8:     MessageBox.Show(data.Text + "\nReceived by: ColleagueA");

   9: }

So you just have to decorate your method with MediatorMessageSink attribute and the Method will get invoked every time a message is broadcasted via the Mediator.

As you can see the Mediator also supports strongly typed parameters. In order to do so you have to specify the ParameterType property on the attribute as shown in the sample code above. You can pass 0 or 1 parameters. If you don’t have any parameters just ignore the ParameterType (since this is an named Property and you can just not set it )

When using the declarative approach you must register the instance of the ViewModel to the Mediator. This is just one line of code in the ViewModel constructor. Here is how you do that

   1: public ColleagueA()

   2: {

   3:     //Register all decorated methods to the Mediator

   4:     Mediator.Register(this);

   5: }

This will inspect all methods of the ViewModel and look for the MediatorMessageSink attribute and register the appropriate methods to the Mediator. If you are going to have a base class for the ViewModels in your project and you can put this in the constructor of your base class. As simple an that.

 

The Imperative approach. (Supported in WPF ONLY)

If you do not want to use the attribute based registration we offer an imperative approach where you specify a method to be registered to a specific message. This implementation is exactly as it was in the old Mediator yet now it supports strongly typed parameters.

Here is how you can use this in your code

   1: public ColleagueC()

   2: {

   3:     //Register a specific delegate to the Mediator

   4:     Mediator.Register(MediatorMessages.Message1,

   5:         (Action<SomeData>)

   6:         delegate(SomeData x) 

   7:         {

   8:             Test = x.Text;

   9:             MessageBox.Show(x.Text + " \nReceived by: ColleagueC"); 

  10:         });

  11: }

This method is supported in WPF only since in Silverlight you cannot call an anonymous method (via reflection). If you try to use this method in Silverlight you will get an InvalidOperationException saying “This method is not supported in Silverlight”.

 

Conclusion

I packaged the Mediator in a class library so that you can go ahead and add a reference and reuse this library in your day to day projects.As always feedback is much appreciated.

Download MediatorLib + Sample application

[MVVM + Mediator + ACB = cool WPF App] – The MVVM

The Model View ViewModel is quite a hot subject right now in the WPF community. If you never read about MVVM I suggest that you read the following before you continue reading

- Introduction to Model/View/ViewModel pattern for building WPF apps by John Gossman (MVVM daddy)

- WPF & Silverlight Line of Business UI Design Pattern by Karl Shifflett

- WPF Apps With The Model-View-ViewModel Design Pattern by Josh Smith

 

MVVM in my sample app

Let me start by showing you a class diagram of the application structure

Desktop

As you can see in the image above we have 3 layers. We have our Views, the ViewModels and the Models. (Please note that you can have n Tiers yet I am focusing just on 2 Tiers here, View and ViewModel….)

The View

The view is the “component” that renders the data on screen. This should be done all in XAML and not in C#. Why? Well UIs are much better built in a declarative fashion instead of an imperative one.

The View can be developed by a designer by using tools such as Blend and should not require any need from a developer. In the View the designer should express his artistic creativeness without any constrains from the developers.

Besides this when you put code in the View, this code is super hard to Unit test. From experiance I must say that 99% of the code written in the UI layer is never tested.

Ok so the designer sets the colors of the buttons etc… BUT!!!!

A - what about the data?  From where can the designer get the data without having C# knowledge?
B – what about actions/events? How can a designer specify that when the button is clicked something should happen?

Well my friends that is the power of the WPF Databinding and the MVVM!

The ViewModel

The ViewModel is just a simple class (That has no coupling with the View and 100% unit testable). The ViewModel exposes data that the View can use to render the UI. Besides this the ViewModel also has Commands that the View can use to invoke actions. I will demo 2 pages that I created in the Sample App that explain how the ViewModel does this job.

A – what about the data?

 DataBinding

To show you how the view renders data exposed by the ViewModel we will take the example in the screen shot above.

The ViewModel involved here is called ProjectListViewModel and the View is called ProjectList.xaml

The ViewModel exposes the data via a property called Projects. The property is shown below

   1: ObservableCollection<WPFDisciples.Backend.ProjectDetails> projects

   2:     = new ObservableCollection<WPFDisciples.Backend.ProjectDetails>();

   3: public ObservableCollection<WPFDisciples.Backend.ProjectDetails> Projects

   4: {

   5:     get { return projects; }

   6: }

As you can see this is simply a normal CLR property (not a DependencyProperty ). In this case the real magic is not in the property as such but in the type of Collection. Since the property exposes an ObservableCollection<T>, the databinding engine will listen to collection changed notifications and update the rendered data according.

This is how we bind to the data in the View’s XAML

   1: <ListView ItemsSource="{Binding Projects}"

In this XAML we are doing List binding. We are specifying to the ListView that it should bind to the Projects property. The question is the Projects property of what object?

By default the source of a Binding is the DataContext of the element. In this case the DataContext will be the ViewModel. We specify that in the constructor of the View. There are many other nicer ways of doing this initialization of ViewModel in the View such as by using Onyx(this is a super cool WPF project!!!!! you must try it) or Dependency injection (such as in PRISM)

   1: public ProjectList()

   2:         {

   3:             InitializeComponent();

   4: 

   5:             var viewModel = new ProjectListViewModel(Dispatcher);
   6:             DataContext = viewModel;

   7:         }

B – what about actions/events?

So let’s say you have a button and you want something to happen when the user clicks the button. Well the approach that we have been using in .Net is events. So a button would have a Click event and you would register an event handler for the event. Yet is this the right approach? Can a designer do this? Can you easily unit test such a method? Well I would say not really or better not easily…

A much better method has been introduced in WPF, the Commands. With commands you can delegate the work (such as a Click event) to the ViewModel. By doing so, the Designer can just specify what command to use for a button and viola he is done. Besides that the ViewModel can be unit tested much easier.

enter data

The example I picked from the sample app is the Save button to add a new Project. This can be found ProjectDetailsViewModel.cs

Here is the code that I used to expose the Command

/// <summary>
/// Gets a Command to save the current project
/// </summary>
public SimpleCommand SaveProject { get; private set; }

Where SimpleCommand is a class that implements the ICommand interface. For more info on this visit this post.

and here is the code for the Command.

SaveProject = new SimpleCommand
            {
                ExecuteDelegate = Save,
                //Can execute only if there are no errors
                CanExecuteDelegate = x => String.IsNullOrEmpty(Project.Error)
            };

Conclusion

This article should have given you a basic idea of how the M V VM works… Next post will discuss how to overcome some of the problems with MVVM. I will show you how you have to start thinking in databinding so that you implement MVVM in a proper way.

DOWNLOAD SAMPLE APP HERE

bye bye Malta…. hello Infusion UK

From 20th April I will start working for Infusion Development, in London UK. This will be a hard move for me… I have my daughter here in Malta so I will still be coming back and forth in weekends. I know this sounds crazy but people do crazy things when they are in love… And I am in love with WPF so it all makes sense :)
I need to do more WPF and Infusion will for sure full fill this need. Being in UK will be cool since a lot of things happen in the UK WPF community. In fact I will be attending the WPF MVVM Training with Microsoft’s one and only Jamie Rodriguez and a special friend of mine Karl Shiflett! not to mention the crazy nights I am planning with one of my best friends Sacha Barber, the article machine :)

I am really looking forward for this!!!! So UK ready or not here I come :)

[MVVM + Mediator + ACB = cool WPF App] – Intro

Finally I managed to spare some time and build a WPF sample application to showcase the use of MVVM + Mediator and also how AttachedCommandBehaviours can be used to further reduce (or better eliminate) C# code in XAML code behind files. I am also using one of my favorite WPF libraries FluidKit. In the app I create my own 3D transition for the FluidKit TransitionPresenter (I will be posting a whole post on this).

I will be posting at least 4 posts

- MVVM

- MVVM and the Mediator pattern

- FluidKit CoverFlow and FluidKit TransitionPresenter

- Using AttachedCommandBehaviours

Here are some teaser screenshots of the application in action :)

Screen1 Screen2

Screen3 Screen4

 

Setup of application environment

This application uses a SQL Database so you will need an instance of SqlServer 2005 running (you can use SqlServer Express).

I packaged the database as a backup so all you need to do is restore the database from the SqlServer Management Studio Express (this is your easiest option). If you don’t have this I suggest you download it, it’s free.

To restore the database file (WPFDisciplesDB.bak) follow these steps

- First of all download the database file from here.

- Right click on the Databases folder in the SQL Server Management Studio Express and select Restore database

Step 1

This will open a dialog for you. In the Restore Database dialog enter a name for the database in the “To database” text field > Select “From device” radio button and browse for the WPFDisciples.bak that you downloaded. The file will appear in the list. Tick the checkbox (which is un checked by default) and press ok.

Step 2 

Now that we have our database set up all we need to do is specify in the app.config the connection string of the new database and we are done.

Stayed tuned because this should be real fun :)

aaaa I nearly forgot… The data in the database is not the full version… I will add more projects from the mighty WPF Disciples as time goes by…. Will continue updating the download link here (and put a comment or something to show you that I updated the db version)

Download Full Source Code from HERE

Just in case you missed it, here is a copy of the database