Serious MessageBus issue

Sep 26, 2012 at 4:57 PM

Hi,

I can't seem to get the message bus working. First from one viewModel to another, then I tried within the same viewModel and it still doesn't work. Just wondering what I'm missing.

In the constructor I register like this:

RegisterToReceiveMessages<KeyValuePair<string, object>>(MessageTokens.Navigation, OnNavigationRequested);

I have a method (specified in the registration above):

        private void OnNavigationRequested(object sender, NotificationEventArgs e)
        {
            ...
        }
I fire a message like this:
MessageBus.Default.Notify(MessageTokens.Navigation, this, new NotificationEventArgs(PageNames.EmployeeView));
This all in the same view model doesn't work, the OnNavigationRequested method is never hit.
Any ideas?
Sep 27, 2012 at 2:21 PM

You may not be using the API correctly.  It changed since I wrote the blog post on the message bus.  You should follow what is in the project documentation, where you can search for the MessageBus section.  There you will see two methods that should be called in two different ViewModels.  In one ViewModel call RegisterToReceiveMessages, passing a string value for the key and the name of the method you want called.  In the other model, call SendMessage, passing the same string key and a NotificationEventArgs parameter, as shown in the documentation.

Let me know if this helps.

Cheers,

Tony

Sep 27, 2012 at 3:15 PM

Hi Tony,

thanks for the swift reply! And it pointed me in the right direction. I had tried SendMessage without success but I found in the documentation that I was registering incorrectly.

//Bad :(
RegisterToReceiveMessages<KeyValuePair<string, object>>(MessageTokens.Navigation, OnNavigationRequested);

//Good :)
RegisterToReceiveMessages(MessageTokens.Navigation, OnNavigationRequested);

That fixed it right up. 

As a side-note, and how easy it was to do this is a real testament to your framework (and Prism). This morning I thought it might be a WPF versus Silverlight issue in the way MessageBus was implemented so as a workaround I ripped the EventAggregator out of Prism and put it into SimpleMVVM along with MEF. And now you've helped me fix the MessageBus I took the EventAggregator right back out again. Dead easy like it should be and as I said, a testament to your framework. (Works really well with MEFedMVVM too if anyone wants a real easy way of MEFing it up).

Cheers,

Tony.

Sep 28, 2012 at 8:18 AM
Edited Sep 28, 2012 at 8:32 AM

Hi,

May I add something that I ran into today.

The message bus is working fine. I am using SendMessage from viewmodel derived from ViewmodelDetailBase to main ViewModel storing the model. The message bus works fine but the method in the RegisterToReceiveMessages seems to be called twice. This is affecting my boolean property as it resets it when it runs the method second time. I am trying to debug it but to no avail. Will keep trying. Could you please let me know if I need to consider anything? The Viewmodel is the only place where I have registered for this messageToken.

Thanks!

In my viewmodel derived from ViewmodeDetailBase:

public void AddToSubregion()
        {
            var orderSubregion = new Dictionary<int, string>{{OrderId,SelectedSubregion.SubregionName}};

            //Ask TreatmentViewModel if the OrderID is available
            SendMessage(MessageTokens.CheckOrderAvailability, new NotificationEventArgs<Dictionary<int,string>,bool>(null,orderSubregion,
                available => Model.AddToSubregion(available,SelectedSubregion.SubregionName,OrderId)));
        }

In main Viewmodel constructor:

RegisterToReceiveMessages(MessageTokens.CheckOrderAvailability, new EventHandler<NotificationEventArgs<Dictionary<int,string>,bool>>(CheckOrderAvailability));
        private void CheckOrderAvailability(object sender, NotificationEventArgs<Dictionary<int,string>,bool> args)
        {
            var available = true;

            var orderId = args.Data.First().Key;
            var subregionName = args.Data[orderId];

            foreach (var subregionRecord in TreatmentLog)
            {
                if (subregionName == subregionRecord.Key.SubregionName)
                {
                    if (subregionRecord.Value.Any(treatment => orderId == treatment.Key))
                    {
                        available = false;
                    }
                }
                break;
            }
            args.Completed(available);
        }
Sep 28, 2012 at 8:53 AM
Edited Sep 28, 2012 at 8:53 AM

This was a quick one. Shouldn't have posted before I ran this test. 

I ran the memory profiler and found out that there were TWO instances of TreatmentViewModel, i.e. main viewmodel in the above example. Hence the method was called TWICE! All good now. Thanks again.

Sep 28, 2012 at 3:14 PM

Hi Tony,

Yes, the signature of your OnNavigationRequested method accepts a NotificationEventArgs parameter - without any generic type arguments.  As the docs explain, NotificationEventArgs can accept an incoming type, as well as an outgoing type, if you specify the additional generic type arguments.  Check out this blog post for additional info on generic parameters and two-way communication.

Really glad you like the toolkit!  It makes my day to get kudos for it and to know that it's helping a lot of folks out there. :-)

Cheers,

Tony