How to load module when using events

179 views Asked by At

I'm very newbie in C#\Prism ecosystem. I want to connect modules via events, but if just send event:

_eventAggregator.GetEvent<LoginSuccessEvent>().Publish(new LoginSuccessEventArgs(user));

then my event handler is not working. As I understand it happens, because reciever ViewModel is not created (I checked with break point in debugger). But if I navigate from event sender:

_regionManager.RequestNavigate(RegionNames.RootRegion, "WorksheetListView");
_regionManager.RequestNavigate(RegionNames.WorksheetDetailsRegion, "WorksheetDetailsView");
_eventAggregator.GetEvent<LoginSuccessEvent>().Publish(new LoginSuccessEventArgs(user));

Then before first RequestNavigate command reciever ViewModel constructor is called.

_regionManager = regionManager;
_model = container.Resolve<WorksheetListModel>();
OpenWorksheetCommand = new DelegateCommand(OpenWorksheet);
Worksheets = _model.WorksheetList;
eventAggregator.GetEvent<LoginSuccessEvent>().Subscribe(OnLoginSuccessEvent);

I tried to add ViewModel class registration to reciever module:

_container.RegisterType<WorksheetListViewModel>();

But no luck. I don't want to add this registration to sender, because hard relation is maked.

But I want to have weak relation between modulel and to do navigation from RECIEVER, but not from SENDER. So sender will don't know anything about reciever. How can I achive this? Thanks.

2

There are 2 answers

3
Sergey Alikin On

Ok. I found a tons of question like ('EventAggregator don't work around modules'). My solution is very easy. I create a instance of my viewmodel, so constructor with event subscribtion is invoked too.

using Microsoft.Practices.Unity;
using Prism.Modularity;
using Prism.Regions;
using Prism.Events;
using Prism.Unity;

using WorksheetListModule.ViewModels;
using WorksheetListModule.Views;
using WorksheetListModule.Models;


namespace WorksheetListModule
{
    public class WorksheetListModule : IModule
    {
        IRegionManager _regionManager;
        IUnityContainer _container;
        IEventAggregator _eventAggregator;

        public WorksheetListModule(RegionManager regionManager, IUnityContainer container, IEventAggregator eventAggregator)
        {
            _regionManager = regionManager;
            _container = container;
            _eventAggregator = eventAggregator;
        }

        public void Initialize()
        {
            WorksheetListViewModel vm = new WorksheetListViewModel(_regionManager, _container, _eventAggregator);
            _container.RegisterInstance<WorksheetListViewModel>(vm);
            _container.RegisterType<WorksheetListModel>();
            _container.RegisterTypeForNavigation<WorksheetListView>();
            _container.RegisterTypeForNavigation<WorksheetDetailsView>();
        }
    }
}

Key feature here is RegisterInstance function. So now I can do navigation in event reciever and event sender now don't know any information about reciever internal structure.

1
Haukinger On

It's a bit unclear what you're trying to achieve, but as far as I get it, your problem's that events are there for those instances that are currently alive. It seems you want more of a state, so that view models that are created after the user logged in can check whether a user is logged in and act accordingly.

I suggest you create a service to hold the currently logged in user and keep the event, because they complement each other nicely.

Example:

public interface IUserManager : INotifyPropertyChanged // this is optional if you keep the event
{
    // returns null if no user is logged in
    string CurrentUserName { get; }

    // returns true if user name and password are valid and updates CurrentUserName
    bool TryLogin( string userName, string password );
}