Codon is a zero-dependency cross-platform MVVM framework for creating UWP, WPF, and Xamarin based applications. It provides much of what you need to rapidly create sophisticated yet maintainable applications.
In the previous article we looked at using Codon’s settings service to store and retrieve settings. In this article, you look at enabling communication between components in your app.
The code presented herein is located in Sample001 in the Samples repository
Communication between components is an essential aspect of any mildly complex app. By using a weak referencing pub/sub messaging system you can decouple components and reduce the likelihood of memory leaks caused by event subscriptions. Codon’s pub/sub messaging service is an implementation of the
IMessenger interface. It allows components in your app to subscribe to message objects of a particular type, and for other components to dispatch those messages. It’s used extensively inside Codon itself for such things as notifying subscribers that a setting has changed.
Understanding the Messenger
IMessenger implementation uses an interface based subscription model. You nominate what messages you’d like your class to receive by implementing the
IMessageSubscriber<T> interface. The CLR
T determines the signature or identity of the message.
This declarative approach to message subscription increases transparency because message subscription is visible at the type level.
To receive messages as they are published, a subscriber needs to call the messenger’s Subscribe method.
NOTE: If you derive from
ViewModelBase the messenger’s Subscribe method is called for you in the base class constructor.
Page1ViewModel class declares a subscription to the
ExampleMessage message by implementing the
IMessageSubscriber<examplemessage> interface. See Listing 1.
Message objects can be POCOs. The `ExampleMessage` class does not derive from a Codon base class.
Behind the scenes, when the
ViewModelBase class calls the messenger’s
Subscribe method, the messenger creates a weak reference to the view-model and calls the
ReceiveMessageAsync(ExampleMessage message) method whenever an
ExampleMessage object is published.
NOTE: You can unsubscribe from the
IMessenger by calling its
Listing 1. Page1ViewModel Implements the IMessageSubscriber<examplemessage> interface.
public class Page1ViewModel : ViewModelBase,
public Task ReceiveMessageAsync(ExampleMessage message)
"Received the message.", "Message from App");
If an object calls the messenger’s
PublishAsync method using an
ExampleMessage object as the parameter, the page receives the message.
Dispatching a Message from the View-Model
Page1ViewModel class contains a
PublishMessageCommand, which is bound to a button in the view.
public ICommand PublishMessageCommand => publishMessageCommand
?? (publishMessageCommand = new ActionCommand(PublishMessage));
When the button is tap/clicked, the
PublishMessage method is called. See Listing 2.
ViewModelBase class contains a
Messenger, which means we don’t need to use the dependency injection to retrieve it.
PublishAsync is an awaitable method, which is useful, for example, if your message object contains a property allowing an action to be cancelled. Codon has some prebaked messages to use for this purpose. An example of which is the
Listing 2: Page1ViewModel PublishMessage method.
void PublishMessage(object arg)
Messenger.PublishAsync(new ExampleMessage(), true);
Tapping the Publish Message button on Page 1 dispatches the message, and it is received within the same view-model. See Figure 1.
Although pointless, it demonstrates how to send and receive a message. You wouldn’t ordinarily subscribe to a message that is only dispatched from the same class.
Figure 1. Dialog box confirms message received.
Pro Tip: Some classes in Codon, such as the
ActionCommand classes implement a global exception handling system. By default, if an exception is raised by one of these classes, the default exception handler class,
LoggingExceptionHandler, logs the exception and request that the exception be rethrown. This alleviates the need to wrap all code blocks in try/catch blocks.
NOTE: While UWP and WPF have the means to catch unhandled exceptions, the same is not true for Android. If there’s an unhandled exception in your Android app, the OS will terminate it. It is recommended that you implement your own IExceptionHandler and register it with the IoC container, like so:
Dependency.Register<IExceptionHandler>(() => new MyExceptionHandler(), true);
In this article, you looked at enabling communication between components using the
Messenger class. In the next part, you look at navigating between pages using the navigation service.
I hope you find this project useful. If so, then please rate it and/or leave feedback below.
April 2 2017