Search code examples
c#wpfprismeventaggregator

How to find out who did not handle an event


We have a rather large application built with C#/WPF/Prism. The application has a few static modules and an unknown number of dynamically loaded modules.

My area of influence is with the static modules and the shell.

I am asked to implement a feature that will restart the shell, but only after querying all currently open modules whether restarting is allowed. If at least one module says it's not allowed (example: still unsaved changes), the restart is postponed.

Now the shell and the modules communicate via the EventAggregator. Which means I can publish an event and then see if any of the subscribers denied or allowed the restart.

This works great for all modules I could change. However, I cannot change the dynamic modules (different teams, different source control).

One requirement was that if any module does not support this new feature, it should be treated as having denied that restart.

The obvious problem is, how do I find out, that somebody did not subscribe to the event?

Although all viewmodels implement our IViewModel interface, I see no way of finding out how many viewmodels currently exist (so I could at least see if all allowed it, or if some answers are simply missing).

I could probably find out, how many modules support it, but even then that says nothing about how many viewmodels are currently open/existing/used by views.

Is there a way to find out if an active viewmodel is not supporting this without changing said viewmodel?


Solution

  • At any given moment you can look at IRegionManager.Regions to find all existing regions. Each IRegion in the collection has IRegion.ActiveViews which gives the list of all currently active views in the region. Then each view (which is an object) may be inspected whether it has some attribute attached or implement some interface. Then, if the view is FrameworkElement, you may also inspect its DataContext.

    If you found a view without attribute/interface, the view does not support restarting. If a view has attribute/interface, you query that interface.

    If you create additional (scoped) region managers, you will need to keep track of them. You maintain a list of active region managers, initially containing only the region manager attached to the shell. While inspecting a view, if the view is a FrameworkElement and has region manager attached to it and that attached region manager is not in the list, you add it to the list and examine the views controlled by that region manager using the same algorithm.