0
votes

UWP Application (Prism.Unity NuGetPackage 6.3.0)

When navigating to the same page several times, a new instance of its view model is created and the old ones are held in memory and are not disposed.

This causes crashes because global events are fired several times using an event aggregator, also received by old ViewModels listening to it.

We're using the NavigationService for navigating through pages. Our pages and usercontrols are bound to viewmodels with prismMvvm:ViewModelLocator.AutoWireViewModel="True" in XAML.

We've seen some threads about similar problems and the solution was to add a region behaviour using Regions. However, as far as I know, Prism UWP doesn't support regions in its current release.

We think the problem is related to the ViewModelLocator and NavigationService, because registering the viewmodels with Container.RegisterType and with a different LifetimeManager has no effect.

A crashing sample can be downloaded from GitHub: App1.zip

Repro:

  1. Execute application
  2. Navigate several times between Test1 and Test2
  3. Hit "RaiseEvent" for executing a global event
  4. All instances logging their hash code
  5. App should crash at some point
1

1 Answers

1
votes

This causes crashes because global events are fired several times using an event aggregator, also received by old ViewModels listening to it.

You could unsubscribe the event when you navigate from one page to another page.

For example:

public class Test1PageViewModel : ShellIntegratedViewModel
{
    private readonly IEventAggregator _eventAggregator;
    private readonly INavigationService _navigationService;
    Action action;
    public Test1PageViewModel(IEventAggregator eventAggregator, INavigationService navigationService)
        : base(eventAggregator)
    {
        _eventAggregator = eventAggregator;
        _navigationService = navigationService;

        NavigateCommand = new DelegateCommand(OnNavigateCommand);
        action = new Action(()=> {
            _eventAggregator.GetEvent<LogEvent>().Publish("Test1 Hashcode: " + this.GetHashCode());
        });
        _eventAggregator.GetEvent<TestEvent>().Subscribe(action);
    }
    private void OnNavigateCommand()
    {
        _eventAggregator.GetEvent<TestEvent>().Unsubscribe(action);
        _navigationService.Navigate("Test2", null);
    }

    public DelegateCommand NavigateCommand { get; private set; }
}