EventAggregator Update GUI

Topics: Prism v4 - WPF 4
May 4, 2015 at 2:38 PM

is there an example how to use the EventAggregator to update the GUI?

I my case, I have a login scenario. The are a couple of things I am checking.
(database available, service available, .etc...)

During this process I send an event to the Shell, but the UI is not updated.
It would be great if there is an example, which shows the best approach. (BackGroundWorker, or Async / await)

Thank you,
May 4, 2015 at 4:50 PM
Take a look at the EventAggregation QuickStart. It demostrates how to use it to communicate and pass data between ViewModels. PubSubEvents in Prism are typically used to communicate between ViewModels, between ViewModels and Services, or Service to Service. If the net result is to update the UI based on the event, that is done by having the event handling update some property in the ViewModel, which causes a change in the View through data binding.

That being said, there is nothing stopping you from subscribing to an event from View code behind other than the guidelines of MVVM. You would just have to make sure you are injecting the singleton EventAggregator instance managed by Prism into the View and call GetEvent<MyEvent>.Subscribe() from there.
May 4, 2015 at 6:00 PM
Edited May 4, 2015 at 6:00 PM
Hi Brian,

this exactly what I am doing.
In the ViewModel of the Shell I Subscript to the event.
this.EventAggregator.GetEvent<WaitWindowEvent>().Subscribe(ShowWaitWindow, ThreadOption.PublisherThread, true);
        private void ShowWaitWindow(WaitWindowEventArgs args)
                IsWaitWindow = Visibility.Visible;
                BusyText = args.Message;
If I debug the code, the event is raised an the ShowWaitWindow() Method is executed.
In both Properties (IsWaitWindow & BusyText) the INotifyProp. Interface is implemented.
If you call the Method in the constructor for example, it works too...

Do you have an idea?
Thank you,
May 4, 2015 at 7:23 PM
Not clear on what is not working then. So the event handler is called and sets those properties. I take it those are bound to something in the UI and nothing is happening when they get set? But are you saying if you just call that from the constructor of the ViewModel then it works? Have you tried changing ThreadOption.PublisherThread to UIThread? That is what you would generally want if the handler is going to be modifying bound properties, but WPF bindings are actually tolerant of setting INPC properties on a separate thread.

Afraid this is the kind of thing that is hard to speculate on with just a few snippets.
May 6, 2015 at 9:57 AM
Thank you for your answer Brian,

if is set the ThreadOption to UIThread, the ShowWaitWindow() method in the ViewModel is executed after the complete Start() method in my StartupManager is done.
The StartupManager looks like this:
private bool Start()
           if (result == true)
                result = LoadActiveCompany();

            if (result == true)
                result = loginManager.CheckUserNameAndPassword(user, password);

            if (result == true)
                result = databaseBiz.UpdateDatabase();

            if (result == true)
                result = CheckHostConnection();

            if (result == true)
                result = CheckLicense();

           private bool CheckHostConnection()
                UpdateWaitWindowText("Checking host connection...");

                this.activeConfiguration.Log("Checking host connection. " + activeConfiguration.WcfServerName);
                return= this.startupBiz.IsServiceAvailable();

            private void UpdateWaitWindowText(string message)
                this.eventAggregator.GetEvent<WaitWindowEvent>().Publish(new WaitWindowEventArgs(message));
May 6, 2015 at 10:33 AM
OK,now I think I understand what you mean by the UI not updating. Is the Start method being called on the UI thread or a separate thread? When you use ThreadOption.UIThread, under the covers it does a Dispatcher.BeginInvoke kind of operation (actually using SynchronizationContext.Post), which queues up the execution for the UI thread once the current execution on the UI thread is complete. So that would explain why you are seeing what you describe.

The right way to get the updates to show at the right time depends on what thread this Start method is executing on as well as other things it calls out to that do similar attempts to update the UI (i.e. your IsServiceAvailable method?).

You can subscribe using ThreadOption.PublisherThread (the default), and then in the handling method use Dispatcher.Invoke - which blocks the current thread execution until the work you give it is done executing on the UI thread - which should mean you will see the transient text in your case before it moves on to the next stage of async execution.

Hope that helps.
May 6, 2015 at 2:09 PM
It seems to be the UI Thread.
If I do this:
Task<bool> result = Task.Factory.StartNew<bool>(Start);
the GUI is working! :)
Unfortunately I am getting the next error from the region manager, but this pretty clear:
 var view = this.regionManager.Regions[ShellRegionNames.Popup].GetView("ILoginViewModel");
Additional information: The calling thread cannot access this object because a different thread owns it.
I didn't expect that updating the UI in the background is that complicated... :(