导航后未放置ViewModel实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了导航后未放置ViewModel实例相关的知识,希望对你有一定的参考价值。

UWP应用程序(Prism.Unity NuGetPackage 6.3.0)

当多次导航到同一页面时,会创建其视图模型的新实例,旧的实例将保留在内存中并且不会被丢弃。

这会导致崩溃,因为全局事件会使用事件聚合器多次触发,也会被侦听它的旧ViewModel接收。

我们使用NavigationService来浏览页面。我们的页面和用户控件绑定到XAML中带有prismMvvm:ViewModelLocator.AutoWireViewModel="True"的视图模型。

我们已经看到了一些关于类似问题的线索,解决方案是使用Regions添加区域行为。但是,据我所知,Prism UWP在当前版本中不支持区域。

我们认为该问题与ViewModelLocator和NavigationService有关,因为使用Container.RegisterType注册viewmodels并使用不同的LifetimeManager无效。

崩溃的样本可以从GitHub下载:App1.zip

演讲嘉宾:

  1. 执行申请
  2. 在Test1和Test2之间多次导航
  3. 点击“RaiseEvent”执行全局事件
  4. 所有实例都记录其哈希码
  5. 应用程序应该在某些时候崩溃
答案

这会导致崩溃,因为全局事件会使用事件聚合器多次触发,也会被侦听它的旧ViewModel接收。

当您从一个页面导航到另一个页面时,您可以取消订阅该事件。

例如:

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; }
}

以上是关于导航后未放置ViewModel实例的主要内容,如果未能解决你的问题,请参考以下文章

导航回上一个选项卡后未显示数据

ViewModel 在导航导航中没有被清除,并且 viewmodel 中的实时数据保持活动状态

在 Angular 4 中导航后未调用组件代码

底部导航片段中的 Viewpager2

清除 sharedViewModel

替换片段后未调用 OnDestroyView 和 OnResume