Reputation: 66320
I am running the latest PRISM 4.2. Unfortunately the Event Aggregator tutorial in the documentation is driven via Unity instead of MEF. And I can't get it running under MEF.
App.xaml.cs
public partial class App : Application
{
[Import]
public IEventAggregator eventAggregator;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
}
}
Bootstrapper.cs
public class Bootstrapper : MefBootstrapper
{
protected override DependencyObject CreateShell()
{
return new MainWindow();
}
protected override void InitializeShell()
{
base.InitializeShell();
App.Current.MainWindow = (Window)Shell;
App.Current.MainWindow.Show();
}
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
}
protected override IModuleCatalog CreateModuleCatalog()
{
ModuleCatalog moduleCatalog = new ModuleCatalog();
return moduleCatalog;
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window, IView
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
MainViewModel.cs:
[ModuleExport(typeof(MainViewModel))]
public class MainViewModel : BindableBase, IServiceCallback
{
[Import]
public IEventAggregator eventAggregator;
[ImportingConstructor]
public MainViewModel()
{
eventAggregator.GetEvent<AppExitEvent>().Publish("");
}
}
Despite the [import]
the event aggregator is always null both in App.xaml.cs and in MainViewModel. Why is that?
The second question is do I have to export my Viewmodels as a module (as I did above) to use an even aggregator inside them?
UPDATE:
Proof that latest version of PRISM doesn't support ComposeExportedValue
anymore.
'System.ComponentModel.Composition.Hosting.CompositionContainer' does not contain a definition for 'ComposeExportedValue' and no extension method ...
Upvotes: 6
Views: 3304
Reputation: 2470
It is a little late, but there is also a solution for the case in which you want the EventAggregator gets injected in property. Implement 'IPartImportsSatisfiedNotification' and use the eventaggregator in 'OnImportsSatisfied' method.
public class MainViewModel : BindableBase, IPartImportsSatisfiedNotification
{
[Import]
public IEventAggregator eventAggregator;
public void OnImportsSatisfied()
{
eventAggregator.GetEvent<AppExitEvent>().Publish("");
}
}
Upvotes: 1
Reputation: 989
The solution to this would be what SchubertJ replied on your same question at CodePlex:
As a deeper analyisis, the Import attribute on Properties would not be resolved until the constructor finishes. That is why you would need to inject the EventAggregator dependency through the constructor as a parameter if this dependency would be used on the constructor implementation.
Therefore, if you would like to use the EventAggregator dependency on the ViewModel constructor, you should use [ImportConstructor] attribute instead, and ask the container for the EventAggregator instance by retreiving it as a parameter:
public class MainViewModel
{
private readonly IEventAggregator eventAggregator;
[ImportingConstructor]
public MainViewModel(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
this.eventAggregator.GetEvent<MyEvent>().Publish("");
}
}
You may find more related information regarding both import alternatives in the following post:
I hope this helped you, Regards.
Upvotes: 7
Reputation: 2716
In your bootstrapper class have this method :
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.ComposeExportedValue(new EventAggregator());
}
You should look at this article as it is answer both your first and second question in better details. http://www.gonetdotnet.info/posts/wpf-articles/wpf-module-communication
Update:
If you create a class as below it will match your export with your import.
public class EventAggProvider
{
[Export(typeof(IEventAggregator))]
public IEventAggregator eventAggregator { get { return new EventAggregator(); } }
}
Upvotes: 1
Reputation: 13765
EventAggregator
does not depend on MEF or Unity
it's design pattern coined by Martin Fowler and it's based on publisher subscriber scenario
try to follow this steps
//this should be in your infrastructure layer
public static class EventAggregatorHelper
{
private static IEventAggregator _Current = new EventAggregator();
public static IEventAggregator Current
{
get
{
return _Current;
}
}
}
The HandleAppExitEvent is a class declared as shown below:
public class AppExitEvent : CompositePresentationEvent<String>
{
}
and the subscriber would be something like this:
in your MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
//In this case the HandleAppExitEvent and the subscriber that deals with this event.
EventAggregatorHelper.Current.GetEvent<AppExitEvent>(). Subscribe(HandleAppExitEvent);
}
//note that this method should be public
public void HandleAppExitEvent(string mess)
{
if (!String.IsNullOrEmpty(mess))
{
//Do whatever you need to do here.
}
}
}
Upvotes: 0