views:

1331

answers:

2

I'm working on a WPF application and is using the Model-View-ViewModel pattern.

The application consists of two modules at the moment:

  • Left Panel to browse a tree and select a node
  • Main Panel to show the content of the selected tree node.

I want to keep these two modules seperated, but when I select a node in the Left Panel I need to fire an event that the Main Panel can subscribe to. I don't want to couple the Left and the Main panel, so I don't want to share instances of the ViewModel classes.

Optimally I would love to use Prism (WPF Composite Application Guidance), but I'm currently extending an existing application and cannot introduce more dependencies. The project is also on .NET 3.0 (not 3.5), so I would have to convert Prism back to .NET 3.0 as it is written for .NET 3.5.

In Prism I would solve this using the Loosely Coupled eventing infrastructure. It allows you to fire an event in any class in any layer, and listen to any event in any class in any layer. Basically the publisher and subscriber of the event is decoupled.

I use Commands to achieve this loose coupling between my View and my ViewModel, but I'm not sure how to do proper cross-View communication.

Any tips or suggestions are greatly appreciated.

I'm specifically looking for a really light weigh pub/sub event model for .NET 2.0/3.0 (no LINQ stuff), or some thing else to implement cross View (module) communication without coupling the two modules.

Update: I ended up solving this in a similar manner to what Glen suggests. I have a separate EventService (I call it a CommandProxy), and pass that one to every ViewModel through the constructors in my service locator (at the moment I'm using a Service Locator instead of a IoC-container). The CommandProxy exposes a set of MultiDelegateCommants, which is an extension of the DelegateCommand in Prism (Composite WPF Guidance). It basically allows Commands that is decoupled from the Visual Tree, and that supports multiple subscribers.

+6  A: 

Do you have an IoC container? One simple approach is to create a custom service that fires the event. Event Aggregator is generic, but you can create a specific service that does what you want.

For example create an EventingService that has a OnNodeSelected method. That method fires a NodeSelected event which hangs off the service. The service is then registered in your IoC container allowing publishers and subscribers to get to it. This way if say your MainPanel needs to subscribe, then your MainPanelViewModel will get injected with the EventingServiec in it's constructor. It will then subscribe. Another approach if you are using WPF is to pull the CompositeCommand from the Composite App Library code and have the eventing service expose a CompositeCommand. Then each subscriber (View Model) registers their command with the service. When the OnNodeSelected is called, the CompositeCommand's execute is invoked, thereby notifying all the interested parties.

We talk about using your own service for this in the docs for Composite App Guidance at www.microsoft.com/compositewpf in the section on Loosely Coupled Events in the Communication topic. (http://msdn.microsoft.com/en-us/library/cc707836.aspx). Francis Cheung also has a post on this.

Glenn Block