1

PRISM 6.2 / EntityFramework 6.3.1 / StockTrader UI / UnityContainer

I acutally having a project with PRISM 5.0.0 and want to update to PRISM 6.2. The project runs fine on 5.0.0, but when I'm updating to 6.2 I got the following problem with the InteractionRequest.

When I navigate to a view/viewmodel with Notifications for the first time, everything works and I can handle the InteractionRequests as usual. If I navigate back and navigate to the view again with a new object, the InteractionsRequest raised the notification twice. (...navigating back and go to again -> raised three times and so on).

In some reasons, the message "This Visual is not connected to a PresentationSource" will occur.

I figure out, that the _invocationCount and _invocationList on the InteractionRequest will not be set to "0"/"null" with PRISM 6.2. So, i think the InteractionRequest will call the notification more than one time. Attached, are screenshots from PRISM 5 and PRISM 6.2.

How can I handle this and solve the problem. In my opinion, it's not a big thing but I actually spent a lot of time to find a solution. Thanks...

PRISM 5.0.0 - working fine

PRISM 6.2 - issue

2017.02.22 Added Sourccode. Software is used to handle devices in datacenters. I deleted all unnecessary sourcecode, but with these files the problem still occur. Perhaps this is a try to find my issue....

Rackmodule.cs -> Initialize Module Rack

public class RackModule : IModule
{
    private readonly IRegionManager _regionManager;
    private readonly IUnityContainer _container;

    public RackModule(IRegionManager regionManager, IUnityContainer container)
    {
        _regionManager = regionManager;
        _container = container;
    }

    public void Initialize() 
    {
        _container.RegisterType<IRackViewModel, RackViewModel>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IRackToolbarViewModel, RackToolbarViewModel>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IRackStatusbarViewModel, RackStatusbarViewModel>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IRackSummaryViewModel, RackSummaryViewModel>(new ContainerControlledLifetimeManager());

        _container.RegisterType<IGeneralDataViewModel, GeneralDataViewModel>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IPlanDataViewModel, PlanDataViewModel>(new ContainerControlledLifetimeManager());
        _container.RegisterType<IRackDataViewModel, RackDataViewModel>(new ContainerControlledLifetimeManager());

        _container.RegisterType<Object, GeneralDataView>(typeof(GeneralDataView).FullName);

        IRegion region = this._regionManager.Regions["MainRegion"];
        var rackView = _container.Resolve<RackView>();
        region.Add(rackView, "RackView");
        region.Activate(rackView);

        IRegion toolbarregion = this._regionManager.Regions["RackToolbarRegion"];
        var toolbarView = _container.Resolve<RackToolbarView>();
        toolbarregion.Add(toolbarView, "RackToolbarView");
        toolbarregion.Activate(toolbarView);

        IRegion statusbarregion = this._regionManager.Regions["RackStatusbarRegion"];
        var statusbarView = _container.Resolve<RackStatusbarView>();
        statusbarregion.Add(statusbarView, "RackStatusbarView");
        statusbarregion.Activate(statusbarView);

        _container.RegisterType<Object, RackSummaryView>(typeof(RackSummaryView).FullName);
        _regionManager.RequestNavigate(RegionNames.RackContentRegion, typeof(RackSummaryView).FullName); 
    }
}

RackSummaryViewModel.cs -> Overview of racks. Go to RackDataView, when click on object

public class RackSummaryViewModel : BindableBase, IRackSummaryViewModel
{
    private readonly IRegionManager _regionManager;
    private readonly IEventAggregator _eventAggregator;
    private readonly IUnityContainer _container;

    public DelegateCommand<SearchEventArgs> OnSearch { get; private set; }
    public DelegateCommand AdvancedRackSearchCommand { get; private set; }

    public InteractionRequest<AdvancedRackSearchNotification> AdvancedSearchRequest { get; private set; }

    private ObservableCollection<RackSummaryEntry> _racks;
    public ObservableCollection<RackSummaryEntry> Racks
    {
        get { return _racks; }
        private set {SetProperty(ref _racks, value);}
    }

    private RackSummaryEntry _currentRack;
    public RackSummaryEntry CurrentRack
    {
        get { return _currentRack; }
        set
        {
            if (SetProperty(ref _currentRack, value))
            {
                if (_currentRack != null)
                {
                    var parameters = new NavigationParameters();
                    parameters.Add("RackID", _currentRack.PrimaryKey.ToString(GuidNumericFormatSpecifier));
                    _container.RegisterType<Object, RackDataView>(typeof(RackDataView).FullName);
                    _regionManager.RequestNavigate(RegionNames.RackContentRegion, new Uri(typeof(RackDataView).FullName + parameters, UriKind.Relative));
                }
            }
        }
    }

    private const string GuidNumericFormatSpecifier = "N";

    public RackSummaryViewModel(IEventAggregator eventAggregator, IRegionManager regionManager, IUnityContainer container)
    {
        _regionManager = regionManager;
        _eventAggregator = eventAggregator;
        _container = container;

        ISessionFactory factory = new SessionFactory();
        container.RegisterType<IRepository, Repository>(new InjectionConstructor(factory.CurrentUoW));

        IUnitOfWork unitOfWork = factory.CurrentUoW;
        IRepository localrepository = new Repository(unitOfWork);

        var query = localrepository.GetList<DMS.Domain.Domain.Rack>();

        Racks = new ObservableCollection<RackSummaryEntry>(query
            .Select(x => new RackSummaryEntry
            {
                PrimaryKey = x.PrimaryKey,
                Country = x.Location.Address.Country,
                City = x.Location.Address.City,
                Street = x.Location.Address.Street,
                Building = x.Location.BuildingName,
                RoomName = x.Location.RoomName,
                RackName = x.RackName,
                RackHeight = x.RackHeight
            }).ToList());
    }
}

RackDataViewModel.cs -> Only Button "Save" und "Go Back"

public class RackDataViewModel : BindableBase, IRackDataViewModel, INavigationAware, IRegionMemberLifetime
    {
        private IRegionNavigationJournal _navigationJournal;
        private readonly IRegionManager _regionManager;
        private readonly IUnityContainer _container;
        private readonly IEventAggregator _eventAggregator;

        public DelegateCommand GoBackCommand { get; private set; }
        public DelegateCommand SaveCommand { get; private set; }

        public InteractionRequest<INotification> SaveNotificationRequest { get; private set; }

        private const string RackIdKey = "RackID";
        private const string EType = "EditType";
        private const string GuidNumericFormatSpecifier = "N";
        public DMS.Domain.Domain.Rack rack;

        // [InjectionConstructor] check if necessary
        public RackDataViewModel(IRegionManager regionManager, IRegionNavigationJournal navigationJournal, IUnityContainer container, IEventAggregator eventAggregator, ILoggerFactory logFactory)
        {
            _regionManager = regionManager;
            _navigationJournal = navigationJournal;
            _container = container;
            _eventAggregator = eventAggregator;

            GoBackCommand = new DelegateCommand(OnGoBackExecute);
            SaveCommand = new DelegateCommand(OnSaveExecute);

            SaveNotificationRequest = new InteractionRequest<INotification>();
        }

        private void OnGoBackExecute()
        {
            if (_navigationJournal != null)
            {
                while (_navigationJournal.CanGoBack)
                    _navigationJournal.GoBack();

                _regionManager.Regions.Remove(RegionNames.RackGeneralDataRegion);
            }
        }

        private void OnSaveExecute() 
        {
            SaveNotificationRequest.Raise(new Notification { Content = "Save changes submitted", Title = "Save changes" });
        }

        public bool KeepAlive
        {
            get { return false; }
        }

        private Guid? GetRequestedRackId(NavigationContext navigationContext)
        {
            var rack = navigationContext.Parameters[RackIdKey];
            Guid rackId;
            if (rack != null)
            {
                if (rack is Guid)
                    rackId = (Guid)rack;
                else
                    rackId = Guid.Parse(rack.ToString());

                return rackId;
            }

            return null;
        }

        bool INavigationAware.IsNavigationTarget(NavigationContext navigationContext)
        {
            var type = navigationContext.Parameters[EType];
            if (rack == null || ((string)type) == "New")
                return true;

            var requestedRackId = GetRequestedRackId(navigationContext);
            return requestedRackId.HasValue && requestedRackId.Value == rack.PrimaryKey;
        } 

        void INavigationAware.OnNavigatedFrom(NavigationContext navigationContext)
        {

        }

        void INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
        {
            Guid? rackId;
            NavigationParameters parameters = new NavigationParameters();

            string key = navigationContext.Parameters[RackIdKey].ToString();
            rackId = GetRequestedRackId(navigationContext);
            parameters = navigationContext.Parameters;

            _regionManager.RequestNavigate(RegionNames.RackGeneralDataRegion, new Uri(typeof(GeneralDataView).FullName + parameters, UriKind.Relative));
            _navigationJournal = navigationContext.NavigationService.Journal;
        }
    }

GeneralDataViewModel.cs -> Is in region of RackDataView with the data of the racks

public class GeneralDataViewModel : BindableBase, IGeneralDataViewModel, INavigationAware
    {
        private IRegionNavigationJournal _navigationJournal;
        private readonly IRegionManager _regionManager;
        private readonly IRepository _repository;

        private const string RackIdKey = "RackID";

        public DMS.Domain.Domain.Rack Rack { get; set; }
        public List<Location> Locations { get; set; }

        public GeneralDataViewModel(IRegionManager regionManager, IRepository repository)
        {
            _regionManager = regionManager;
            _repository = repository;
        }

        private Guid? GetRequestedRackId(NavigationContext navigationContext)
        {
            var rack = navigationContext.Parameters[RackIdKey];
            Guid rackId;
            if (rack != null)
            {
                if (rack is Guid)
                    rackId = (Guid)rack;
                else
                    rackId = Guid.Parse(rack.ToString());

                return rackId;
            }
            return null;
        }


        bool INavigationAware.IsNavigationTarget(NavigationContext navigationContext)
        {
            if (Rack == null)
                return true;

            var requestedRackId = GetRequestedRackId(navigationContext);
            return requestedRackId.HasValue && requestedRackId.Value == Rack.PrimaryKey;
        }

        void INavigationAware.OnNavigatedFrom(NavigationContext navigationContext)
        {
            // Intentionally not implemented.
        }

        void INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
        {
            var rackId = GetRequestedRackId(navigationContext);
            Rack = _repository.GetEntity<DMS.Domain.Domain.Rack>(rackId);

            _navigationJournal = navigationContext.NavigationService.Journal;
        }
    }
  • Questions: When you first navigate to a view, is it's view model registering any composite commands? Or, subscribing to any PubSub Events? – R. Richards Feb 17 '17 at 22:11
  • Yes, I have Subscribe-Commands for refreshing objects. But when I comment these commands, nothing will change and the problem still exists. No sourcecode changes were done before updating to 6.2; expect the namespaces of 6.2 When I have a look in the invocationlist of the attached screenshot, the target refers to the InteractionRequestTrigger. In my case the InteractionRequest will not destroy the InteractionRequestTrigger target, when reopen a new view. – Bavariaurbs Feb 20 '17 at 13:05
  • The times that I have seen this behavior is when I register a composite command, and do not unregister it when navigating away from the associated view. Same thing with Pub/Sub events, subscribing, but not unsubscribing. Look to see if something like that is going on. Also, confirm that the commit in your repo/UoW is completing successfully. – R. Richards Feb 20 '17 at 13:36
  • It sounds like this behavior, but in my case I think it's something different. Between _regionmanager.RequestNavigate(RegionNames.ContentRegion, typeof(ContentView).FullName, parameters) and void INavigationAware.OnNavigatedTo(NavigationContext navigationContext) something count the invocationList. In the Release Notes of Prism 6.0.0 there is fix called "Fixed bug in which the InteractionRequestTrigger would not raise notifications when navigating away from and back to a view". Perhaps this fix will raise my issue?!? – Bavariaurbs Feb 21 '17 at 14:29
  • Can you add the relevant parts of the view model code to the question? Or, all of it, if it isn't too big? – R. Richards Feb 21 '17 at 14:48
  • ok, i added some viewmodels, but I didn't find something to highlight the text as C#. --> Going from RackSummaryViewModel to RackDataViewModel, I can call "OnSaveExecute()". If i go back and to the view again and press "OnSaveExecute()", the InteractionRequest have more than one InvacationCount... – Bavariaurbs Feb 22 '17 at 12:39
  • Comment out the line in `RackSummaryViewModel` ctor that subscribes to `RackListRefreshEvent`, run the application, tell me if the issue persists. – R. Richards Feb 22 '17 at 12:54
  • I removed the RackListRefreshEvent (see sourcefiles) completly, but nothing changed. Issue still persists. – Bavariaurbs Feb 22 '17 at 13:58

0 Answers0