Should I use a MessageBus to push UI notification

119 views
Skip to first unread message

Fares Eidi

unread,
Jun 26, 2015, 2:34:23 PM6/26/15
to reacti...@googlegroups.com
I was looking to make use of the MessageBus to allow my open windows (in tabs) to push notification messages to the main window hosting these tabs.

I got worried when I read the post http://log.paulbetts.org/messagebus-and-why-you-shouldnt-use-it/   which suggest that the MessageBus should be used only as a last resort. 

I was just wondering what alternatives exist for doing a messaging service using reactiveUI ?


Matt Oswald

unread,
Jun 27, 2015, 9:13:09 AM6/27/15
to reacti...@googlegroups.com

I’m assuming the main window’s view model hosts the tabs’ view models in some sort of collection. When the TabViewModel is created, pass an observable (held by the MainWindowViewModel) into their constructors, and use that. Now you no longer have global state to maintain!

 

--m

--
You received this message because you are subscribed to the Google Groups "ReactiveUI mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to reactivexaml...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Fares Eidi

unread,
Jun 27, 2015, 3:16:23 PM6/27/15
to reacti...@googlegroups.com
Hi Matt,

I appreciate your response, I am just starting out with this, so please excuse my having to ask what you mean by "pass an observable "?
 
Are you suggesting I hold a single instance of MessageBus.Current in a member variable in the MainViewModel and pass it along (via constructor) into each TabViewModel as it is being initialized ?

Or did you mean something altogether different ?

Fares

--
You received this message because you are subscribed to a topic in the Google Groups "ReactiveUI mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/reactivexaml/fVwQ7y_JX7s/unsubscribe.
To unsubscribe from this group and all its topics, send an email to reactivexaml...@googlegroups.com.

Matt Oswald

unread,
Jun 27, 2015, 3:32:17 PM6/27/15
to reacti...@googlegroups.com

Hi Fares,

 

Something altogether different. J

 

Instead of creating a MessageBus to deal with passing around objects of type NotificationMessage, instead have the TabViewModel constructor expect a parameter of type IObservable<NotificationMessage>, which MainViewModel can fill however it wants (probably a member variable Subject<NotificationMessage>).

Fares Eidi

unread,
Jun 27, 2015, 4:23:40 PM6/27/15
to reacti...@googlegroups.com
Hmm... interesting approach,
I suppose this would work, because the IObservable is a sort of publish / subscribe pattern implementation, (which is I guess the functionality that a message bus was supposed to add.... right ?

Matt Oswald

unread,
Jun 27, 2015, 4:27:38 PM6/27/15
to reacti...@googlegroups.com

Correct.

Fares Eidi

unread,
Jun 28, 2015, 4:17:55 AM6/28/15
to reacti...@googlegroups.com
Matt,

I've discussed with my colleague, do you perhaps mean  passing an IObserver instead of an IObservable, which has an OnNext method (used to push item):
 
1 - In view model:
 
        IObserver<string> notifications;
        public CaptureDealViewModel(IApiFactory api, IObserver<string> notifications)
        {
            this.notifications = notifications;
            …
        }
 
        private Task Capture(IApiFactory api)
        {
            // Send notification using IObserver.OnNext to push item
            notifications.OnNext("Deal capture...");
            …
        }          
 
2 - In main window view model constructor:
       
        public MainWindowViewModel()
        {    
            var subject = new System.Reactive.Subjects.Subject<string>();
       
            //Subject<T> is a special kind of object in Rx which is both IObservable and IObserver  
            IObserver<string> observer = subject;


3 - We pass the observer to the view models constructor:      
 
            this.OpenCaptureDeal = ReactiveCommand.CreateAsyncTask(
               Observable.Return(HasUserRights()),
               _ => Task.FromResult(AddTab("Capture Deal", new CaptureDealViewModel(api, observer))));
           
 
4 - And we also add an IObservable property in the main window view model and assign subject to it:
 
            this.Notifications = subject;
        }
 
        public IObservable<string> Notifications { get; private set; }
            


5 - Finally in the MainWindowView:
 
            d(this.WhenAnyObservable(v => v.ViewModel.Notifications)
                    .Subscribe(ShowDesktopNotification));       



Are we on the right track ?

Matt Oswald

unread,
Jun 28, 2015, 9:55:46 AM6/28/15
to reacti...@googlegroups.com
1 - Give CaptureDealViewModel a public IObservable<string> Notifications {get;}
    This can be a subject, or you can initialize it with Observable.Create(...) or whatever.

2 - MainWindowViewModel needs a private Subject<string> _notifications;

3 - MainWindowViewModel needs a public IObservable<string> Notifications { get { return _notifications.AsObservable(); }}

4 - When MWVM creates a CDVM, it should subscribe to the Notifications:
    var cdvm = new CaptureDealViewModel(api);
    var cdvmSubscription = _notifications.Subscribe(cdvm.Notifications);
    // make sure to track cdvmSubscription, because you need to dispose of it if cdvm is ever disposed

5 - Have your MainWindowView subscribe to MainWindowViewModel.Notifications

You were pretty close, but there's no need to set up a "MessageBus" inside the main view model. The CaptureDealViewModel can create everything it needs on its own, which will reduce dependencies and make it easier to test.

--m
Reply all
Reply to author
Forward
0 new messages