Guidance on when to use different communication patterns

Topics: Prism v1, Prism v2 - Silverlight 2, Prism v2 - WPF 3.5
Jun 18, 2009 at 2:12 AM

Hi,

One thing I've noticed from the various quickstarts / RI is that whilst they show every possible way to communicate between views / modules they don't really offer any guidance as to when each is applicable.

For example,

The Digg / Twitter Search example which uses EventAggregator to ask each search provider to search.

The StockTrader RI uses DelegateCommands hanging off a Controller to buy / sell stock, and CompositeCommands to Buy All / Sell All.

I want to understand under which circumstances is it appropriate to use each. My instinct tells me that an Event should be used to publish the fact that something happened which might interest other people whilst a Command dictates that some action will occur Following this interpretation the Digg Search should use a Command and not an Event to get the Search to happen. An event would be appropriate when the Search Results are returned - for example maybe an advertising view would be interested in this to tailor adverts.

What are other people's takes on when to Event and when to Command?

Thanks,

Graeme

Jun 19, 2009 at 3:14 PM

I do agree that Commands are deterministic whereas Events are not.

Events are best for extensibility - providing ready notifications for unwritten plug-ins - e.g. new modules for more search engines that can be deployed onto the existing app.

Jun 19, 2009 at 6:31 PM

Hi Graeme,

 

There are some documents from the Prism-v2 documentation that provide some advice on when to Commands/Event Aggregator:

·         Communication

·         Event Aggregator

·         Commands

 

I will provide some more information, that expresses my personal point of view.

 

The EventAggregator, should be used to communicate between different modules to notify that a particular thing has happened. When you publish an event through EventAggregator you do not know who is listening, so perhaps no immediate action will be performed. For example, when you are processing some business logic (in controllers/presenters/viewmodels) and want to notify something to another module you could use EventAggregator. Ward Bell posted a good explanation about the Event Aggregator Pattern.

 

Commands on the other hand “know” the code that will be executed when they are fired, it is always the same and are more UI related. If you require a specific action to be executed that is related to UI, you should use commands.

 

If you feel that a particular scenario could be implemented with any of these, I would examine the pros and cons of each of the approaches and take the one that best suits the scenario.

 

I hope my explanation has been useful, but I really recommend reading the above links (specially communication) which will probably provide much more information.

 

Please let me know if this helps.

 

Damian Schenkelman

http://blogs.southworks.net/dschenkelman

Jun 20, 2009 at 12:46 PM

Hi Daniel,

Thanks for the information - can I run a specific scenario past you to get some clarity - I'm getting a bit confused and suspect I'm complicating my own thoughts.

I have a Shell which consists of 2 regions. I've called one the 'Customer Finder' and another the 'Customer Details'.

Customer Finder is a simple search view which takes a name, then shows a list of customers. When the user selects a customer I want to show their details in the details region. The details region is not linked to the finder because I'd like other routes by which to show a customer - maybe deep linking from outside the application.

I've currently got a CustomerUIService which has a method, ShowCustomer(id). The Customer Finder view model takes this in its constructor and calls it when you select a customer. The CustomerUIService keeps track of which customers are currently open and either shows an existing one, or adds a new one. View Discovery then takes care of loading all the views which show the details. What I keep going backwards and forwards on is if this interaction should be based on an event fired by the Customer Finder.

Cons for an event are that when you select a customer it's pretty clear what needs to happen (in this particular usage). Also I think events are loaded with the expectation that nothing may happen. I don't like firing an event when I know something should happen.

Pros for an event are that maybe other people are interested in the fact that a customer was selected. It also feels like how Prism wants me to communicate between views which aren't linked.

I would love to know your take on this.

Thanks,

Graeme

 

Jun 23, 2009 at 7:32 PM

Hi Graeme,

 

In this particular situation I agree with you, in the fact that an event should be published to notify that the customer was selected (in fact in a demo application I have helped creating recently we did it like that).

Actually what we did was creating a DelegateCommand with an attached behavior for the SelectionChanged event of a WPF DataGrid. Each time we selected a new customer, the command would be fired. The code for that command simply fired an event through event aggregator (passing the Customer as payload), which was handled by another view’s presenter.

 

In your scenario, the event could be handled by a “module controller” in the module that has the CustomerDetails view (by a “module controller” I mean something that knows things about the entire module, not just a single view like a Presenter/ViewModel).

This controller could use a service (I do not know how your CustomerUIService is implemented), or simply a list of the customer’s whose details are already being shown. Then, if the customer is in that list, it could perform the logic to make it visible in the details region, and else create a new view and show it.

 

Although I do not know your application scenario, if you only show one customer details view at the same time (using a SingleActiveRegion), you could have a single instance of the CustomerDetails view, and just change the data context based on the selected customer. This is not completely related with your question, but it might save you unnecessary view creation.

 

Please let me know if this helps.

 

Damian Schenkelman

http://blogs.southworks.net/dschenkelman

Jun 24, 2009 at 7:14 AM

Thanks for the info Dan,

I'm actually presenting on this tomorrow night at a Perth (Australia) community event and worked over the weekend coming up with this approach. I wanted to introduce bits of Prism slowly -

Firstly I have the search window. Part of the "application requirements" are to show user details when you select a customer. This is done with a ContentControl which is bound to the DataContext of the search results. These are CustomerViewModel objects and I use WPF Data Templates to marry the data object to the visual.

Then the 2nd requirement is to allow other modules to plug-in to the view. So I add a TabRegion to the page with the name 'CustomerDetails'. Then when a customer is selected (binding from list box to property via ListBox.SelectedItem) I raise a Prism event 'SelectedCustomerChanged' which is subscribed to by the view in the separate module.

I wanted to demonstrate RegionContext but it doesn't work with the pure ViewModel approach. Shame.

Cheers,

Graeme