Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way of using MVVM Light Messenger

What is the proper way to use Messenger class ? I know it can be used for ViewModels/Views communications, but is it a good approach to use it in for a technical/business service layer ?

For example, a logging/navigation service registers for some messages in the constructors and is aware when these messages occurs in the app. The sender (ViewModel ou Service) does not reference the service interface but only messenger for sending messages. Here is a sample service :

using System;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using App.Service.Interfaces;
using GalaSoft.MvvmLight.Messaging;

namespace App.Service
{
    public class NavigationService : INavigationService
    {
        private PhoneApplicationFrame _mainFrame;

        public event NavigatingCancelEventHandler Navigating;

        public NavigationService()
        {
            Messenger.Default.Register<NotificationMessage<Uri>>(this, m => { this.NavigateTo(m.Content); });
        }

        public void NavigateTo(Uri pageUri)
        {
            if (EnsureMainFrame())
            {
                _mainFrame.Navigate(pageUri);
            }
        }

        public void GoBack()
        {
            if (EnsureMainFrame()
                && _mainFrame.CanGoBack)
            {
                _mainFrame.GoBack();
            }
        }

        private bool EnsureMainFrame()
        {
            if (_mainFrame != null)
            {
                return true;
            }

            _mainFrame = Application.Current.RootVisual as PhoneApplicationFrame;

            if (_mainFrame != null)
            {
                // Could be null if the app runs inside a design tool
                _mainFrame.Navigating += (s, e) =>
                {
                    if (Navigating != null)
                    {
                        Navigating(s, e);
                    }
                };

                return true;
            }

            return false;
        }
    }
}
like image 483
Cybermaxs Avatar asked Aug 31 '12 07:08

Cybermaxs


1 Answers

For me, the main use of a messenger is because it allows for communication between viewModels. Lets say you have a viewmodel that is used to provide business logic to a search function and 3 viewmodels on your page/window that want to process the search to show output, the messenger would be the ideal way to do this in a loosely-bound way.

The viewmodel that gets the search data would simply send a "search" message that would be consumed by anything that was currently registered to consume the message.

The benefits here are:

  1. easy communication between viewmodels without each viewmodel having to know about each other
  2. I can swap out the producer without affecting a consumer.
  3. I can add more message consumers with little effort.
  4. It keeps the viewmodels simple

Edit: So, what about services?

ViewModels are all about how to present data to the UI. They take your data and shape it into something that can be presented to your View. ViewModels get their data from services.

A service provides the data and/or business logic to the ViewModel. The services job is to service business model requests. If a service needs to communicate/use other services to do its job these should be injected into the service using dependency injection. Services would not normally communicate with each other using a messenger. The messenger is very much about horizontal communication at the viewmodel level.

One thing I have seen done is to use a messenger as a mediator, where instead of injecting the service directly into a viewmodel the messenger is injected into the viewmodel instead. The viewmodel subscribes to an event and receives events containing models from the event. This is great if you're receiving a steady flow of updates or you're receiving updates from multiple services that you want to merge into a single stream.

Using a messenger instead of injecting a service when you're doing request/response type requests doesn't make any sense as you'll have to write more code to do this that you'd have to write just injecting the service directly and it makes the code hard to read.

Looking at your code, above. Imagine if you had to write an event for each method on there (Navigate, CanNavigate, GoBack, GoForward, etc). You'd end up with a lot of messages. Your code would also be harder to follow.

like image 85
Faster Solutions Avatar answered Oct 31 '22 08:10

Faster Solutions