Leaky
Leaky

Reputation: 3636

NullReferenceException in Caliburn.Micro's DisplayRootViewFor method when trying to use EventAggregator

I'm trying to use Caliburn Micro's built-in EventAggregator in my WPF project, based on this documentation. But the documentation (as I almost always find it with Caliburn Micro) seems incomplete, i.e. the sample code doesn't contain all implementation requirements.

In particular, I wasn't using an IoC container in my project, and I'm sure I'm missing or misusing some part of its configuration, and that is causing the issue.

The problem:

Notes:

Could somebody explain to me why does Caliburn.Micro throw this exception, and how I'm supposed to inject the EventAggregator to my main viewmodel? (Because trying to pass it as a parameter in DisplayRootViewFor didn't seem to work.)


My app bootstrapper looks like the following – based on the combination of The Event Aggregator and the Simple IoC Container documentation pages:

public class AppBootstrapper : BootstrapperBase
{
    private readonly SimpleContainer _container =
        new SimpleContainer();

    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        _container.Singleton<IEventAggregator, EventAggregator>();
    }

    protected override object GetInstance(Type serviceType, string key)
    {
        return _container.GetInstance(serviceType, key);
    }

    protected override IEnumerable<object> GetAllInstances(Type serviceType)
    {
        return _container.GetAllInstances(serviceType);
    }

    protected override void BuildUp(object instance)
    {
        _container.BuildUp(instance);
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor<MainViewModel>();
    } 
}

And my MainViewModel's constructor looks like the following – set up for injecting the EventAggregator:

public MainViewModel(IEventAggregator eventAggregator)
{
    _eventAggregator = eventAggregator;
}

Upvotes: 4

Views: 1961

Answers (2)

Techiemanu
Techiemanu

Reputation: 646

Additionally following piece of code with registering each ViewModel also worked for me

public class BootStrapper : BootstrapperBase {

    protected SimpleContainer _container = new SimpleContainer();
    public BootStrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        _container.Instance(_container);
        _container
            .Singleton<IWindowManager, WindowManager>()
            .Singleton<IEventAggregator, EventAggregator>();

        GetType().Assembly.GetTypes()
            .Where(type => type.IsClass)
            .Where(type => type.Name.EndsWith("ViewModel"))
            .ToList()
            .ForEach(viewModelType => _container.RegisterPerRequest(
                viewModelType, viewModelType.ToString(), viewModelType));
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor<ShellViewModel>();
    }

    protected override object GetInstance(Type service, string key)
    {
        return _container.GetInstance(service, key);

    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return _container.GetAllInstances(service);
    }

    protected override void BuildUp(object instance)
    {
        _container.BuildUp(instance);
    }
}

Upvotes: 0

mm8
mm8

Reputation: 169270

Use the RegisterPerRequest to register the view model type itself. Try this:

public class HelloBootstrapper : BootstrapperBase
{
    private readonly SimpleContainer _container = new SimpleContainer();
    public HelloBootstrapper()
    {
        Initialize();
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        base.OnStartup(sender, e);
        DisplayRootViewFor<MainViewModel>();
    }

    protected override void Configure()
    {
        _container.Singleton<IWindowManager, WindowManager>();
        _container.Singleton<IEventAggregator, EventAggregator>();
        _container.RegisterPerRequest(typeof(MainViewModel), null, typeof(MainViewModel));
    }

    protected override object GetInstance(Type serviceType, string key)
    {
        return _container.GetInstance(serviceType, key);
    }

    protected override IEnumerable<object> GetAllInstances(Type serviceType)
    {
        return _container.GetAllInstances(serviceType);
    }

    protected override void BuildUp(object instance)
    {
        _container.BuildUp(instance);
    }
}

Upvotes: 10

Related Questions