DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Implement a Simple Messenger for MVVM User Controls and Apps

Learn more about implementing a Singleton class that will listen for changed values, creating a messenger.

Marco Siccardi user avatar by
Marco Siccardi
·
Aug. 29, 15 · Tutorial
Like (2)
Save
Tweet
Share
4.78K Views

Join the DZone community and get the full member experience.

Join For Free

User controls are awesome. You put together a simple to use (in the best case, that is) component to reuse in your project(s). Sometimes, you even put that control into a (portable) class library to make it available across platforms. Most user controls are written without MVVM, using just DependencyProperties and the matching code behind file.

But – it is possible to create a user control that comes with its own ViewModel, keeping only the DependencyProperties in code behind. There are some limits when it comes to values that are generated by the view of your control. You can’t get them into your ViewModel without creating a reference to it (which may break the MVVM pattern in some eyes). Well, some will argue “who cares, I need to get this working, so I am getting a reference to the DataContext." This is ok, but there is also another, in my opinion more elegant solution. A class that listens for those changed values, pulling them into your ViewModel – a so called messenger.

Some of you might have used a Framework/Toolkit like MVVMLight, Prism, or similar. If you want to use them in a class library, you will find some stones in your way like a missing ViewModelLocator and more. At work, I am working on a universal user control for our LOB applications. Since the control involves a lot of values from its view, I needed a smart and fast way to get those into my ViewModel. I achieved it with my own simple messenger, enabling me to avoid any Framework/Toolkit in my control.

Here is how I did it. First I created a new Singleton class. If you do not know what a Singleton is, just click on the link in the sentence before. Long story short: a Singleton makes the class static, and makes sure that there is only one instance that all other classes are working with (to ultimately get the correct values). Hint: it may happen that due to some bad timing, you are still having more than one instance. In this case, you should have a look into a different way of implementation the call to the Singleton instance.

In my case, I am using the simple implementation, which automatically creates the first instance if there is none:

    public class SimpleMessenger
    {
        private static SimpleMessenger _instance;

        public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
     }

The next step is to create an EventHandler, that informs us when the SimpleMessenger has new values. It makes absolutely sense to create your own EventArgs to be passed into the EventHandler. Just collect the data that you want to provide in a class that derives from EventArgs, and make the EventHandler using this class as its event data:

        //declaring EventHandler
        public event EventHandler<MessageValueChangedEventArgs> MessageValueChanged;


        //custom event args class
        public class MessageValueChangedEventArgs : EventArgs
        {

            public string PropertyName { get; set; }

            public object OldValue { get; set; }

            public object NewValue { get; set; }
        }

The most important function in this class is to raise the event:

        //raising the event for a property
        public void RaiseMessageValueChanged(string propertyName, object oldValue, object value)
        {
            MessageValueChanged?.Invoke(this, new MessageValueChangedEventArgs() { PropertyName = propertyName, NewValue = value, OldValue = oldValue });
        }

I am using just three basic values that are needed: the name of the property that changed, its old and its updated value. This already enables me to send data between View and ViewModel, or even to outside of my control. Of course, you want to see how one does send “messages” with my SimpleMessenger. It’s pretty simple, too.

First, you need to get a reference to the current instance:

        private SimpleMessenger _simpleMessenger;

        public MainPage()
        {
            this.InitializeComponent();

            _simpleMessenger = SimpleMessenger.Instance;
         }

To send data, just use the RaiseMessageValueChanged event:

_simpleMessenger.RaiseMessageValueChanged("RootGridSize", e.PreviousSize, e.NewSize);

Last but not least, we are also able to read those values in some other place:

        private SimpleMessenger _simpleMessenger;

        public MainViewModel()
        {
            _simpleMessenger = SimpleMessenger.Instance;
            _simpleMessenger.MessageValueChanged += OnSimpleMessengerValueChanged;
        }

        private void OnSimpleMessengerValueChanged(object sender, SimpleMessenger.MessageValueChangedEventArgs e)
        {
            if (e.PropertyName == "RootGridSize")
            {
                var size = (Size)e.NewValue;

                Debug.WriteLine($"Current Size: {size.Height}x{size.Width}");
            }

        }

As you can see, it is simple to use this class to get values in decoupled way (like the MVVM pattern requires). Of course, you still have to take care not to overuse this. I am using it for example to get the changed values of DependencyProperties that my control has into the ViewModel (which would otherwise only be possible with a reference to it).

This SimpleMessenger may not be as powerful as those in the popular Frameworks/Toolkits, but for usage in user controls or small apps it should fit in perfect.  I attached a very simple project to demonstrate the SimpleMessenger. Just start the project, and use your mouse to resize the app window. It will write the Size of the root grid to the console.

Download sample

As always, I hope this post is helpful for some of you.

app Messenger (software)

Published at DZone with permission of Marco Siccardi, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • What Was the Question Again, ChatGPT?
  • How to Submit a Post to DZone
  • Microservices Discovery With Eureka
  • What Is a Kubernetes CI/CD Pipeline?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: