DevExpress MVVM Framework. Interaction of ViewModels. Messenger.

13 December 2013

OTHER RELATED ARTICLES:

  1. Getting Started with DevExpress MVVM Framework. Commands and View Models.
  2. DevExpress MVVM Framework. Introduction to Services, DXMessageBoxService and DialogService.
  3. DevExpress MVVM Framework. Interaction of ViewModels. IDocumentManagerService.
  4. DevExpress MVVM Framework. Introduction to POCO ViewModels.
  5. THIS POST: DevExpress MVVM Framework. Interaction of ViewModels. Messenger.
  6. DevExpress MVVM Framework. Using Scaffolding Wizards for building Views.
  7. DevExpress MVVM Framework. Data validation. Implementing IDataErrorInfo.
  8. DevExpress MVVM Framework. Using DataAnnotation attributes and DevExpress Fluent API.
  9. DevExpress MVVM Framework. Behaviors.
  10. DevExpress MVVM Framework. TaskbarButtonService, ApplicationJumpListService and NotificationService.
  11. DevExpress MVVM Framework. Asynchronous Commands.
  12. DevExpress MVVM Framework. Converters.


An application’s architecture depends on the degree of connection between its modules. Loosely-coupled systems are suited for large applications. This usually means many scattered modules, operating without awareness of each other. Ideally, modules are the building blocks of an adaptive design. Loosely-coupled architectures are easy to support and improve because adding or removing functionality simply means registering or unregistering a specific module without concern towards the others.

To facilitate interaction between modules, we implemented a class to exchange messages regardless of which module is sending or receiving the message. This class is Messenger.

Let’s examine a simple sample to get a clearer understanding.

Imagine we have a database which can be modified from several modules. One module will need to be notified when modifications happen (e.g., adding, removing, and changing a record). We’ll first need to create a message:

   1: public enum MessageType { Added, Deleted, Changed }
   2: public class Message {
   3:     public MessageType MessageType { get; private set; }
   4:     public object RecordID { get; private set; }
   5:     public Message(object recordID, MessageType messageType) {
   6:         RecordID = recordID;
   7:         MessageType = messageType;
   8:     }
   9: }

We can then subscribe to the message from anywhere in the application. For instance:

   1: public class Module1 {
   2:     public Module1() {
   3:         Messenger.Default.Register<Message>(this, OnMessage);
   4:     }
   5:     void OnMessage(Message message) {
   6:         switch(message.MessageType) {
   7:             case MessageType.Added:
   8:                 //...
   9:                 break;
  10:             case MessageType.Changed:
  11:                 //...
  12:                 break;
  13:             case MessageType.Deleted:
  14:                 //...
  15:                 break;
  16:             default:
  17:                 throw new NotImplementedException();
  18:         }
  19:     }
  20: }

Sending a message is even easier:

   1: public class Module2 {
   2:     void SendMessage() {
   3:         Messenger.Default.Send(new Message(0, MessageType.Added));
   4:     }
   5: }

As you can see, this approach implements module interaction without reference to a module’s code. Even if you remove Module1 or Module2 while developing the application, it will not cause errors and the entire system will continue to function.

We also prepared a real example with this architecture. It can be found here. Screenshots of the example are below.

4.Blog.Messaging.001

4.Blog.Messaging.002

8 comment(s)
Geert Depickere

Does a module also need to un-register (to prevent memory leaks) or does this happen auto-magically?

13 December, 2013
Alexander (DevExpress Support)

Hi Geert,

Good question. No, by default Messenger works with weak references, so you may not unregister message handlers and it will not cause memory leaks.

13 December, 2013
CARREAU Clément

Hi,

Can't we send a void Message ( like Messenger.Default.Send(); ) just to notify the other ViewModel that it has to do something right now ?

1 July, 2014
Alexander (DevExpress Support)

Hello,

I apologize for the late response, I was on vacation. In the future, if you have a technical question, I suggest you contact our support team. In this case, you will get our assistance faster, because different engineers can process your inquiries.

As for your question, no, it is impossible to raise a void message. I understand what you wish to implement, but it is unclear how to implement this feature technically. In a common case, if you raise a void message, every recipient of every message should be called with the Null message. However, I do not know what to do if a recipient is subscribed to a not Nullable message type (enum or struct)?

I think that for such a scenario, you can create a special message that will be used by your every message recipient. As an alternative, you can use the following sending method:

Messenger.Default.Send<string>(null);

8 July, 2014
3TM5VX2BJj3

The URL for the working example throws SQL exceptions using 17.1

1 June, 2017
Alexander (DevExpress Support)

Fixed. Thanks!

6 June, 2017
Barbara Nunes

Can the messenger be resolved using a container?

6 June, 2017
Alexander (DevExpress Support)

Yes, you can register the Messenger in your ServiceLocator.

BTW, if you need to separate messages, you can use message tokens. It is described in the documentation: documentation.devexpress.com

7 June, 2017

Please login or register to post comments.