在Prism/Composite MVVM WPF应用程序中使视图模型激活感知

4
在我的MVVMC应用程序中,我有一个包含多个步骤的过程,基本上是一个向导。
我的控制器解析了外部视图(称之为WizardView),并将其添加到主区域。 WizardView包含一个面包屑导航,用于显示通过向导的进展情况,并包含一个子区域,用于加载其他视图(称之为WizardRegion)。 Step1View 是加载到WizardRegion中的第一个视图。
每个视图都将其ViewModel注入构造函数中,使用Unity容器进行注入。 WizardViewModel订阅了几个事件聚合事件,这些事件由步骤视图模型发布。
当每个步骤完成时,View Model会发布一个事件,WizardViewModel使用它来存储状态,这意味着WizardViewModel正在收集我们进行的每个步骤的数据。 步骤ViewModel还调用控制器来将下一步加载到WizardRegion中。
在最后一步中,WizardViewModel保存向导的结果,并且MainRegion导航回其他屏幕。
下次进入向导时,我们创建所有视图和ViewModels的新实例,但是先前向导的事件订阅仍然存在。
如何使我的视图模型意识到它们已被停用,以便我可以取消订阅我的事件?
另一个选项是在事件处理程序中取消订阅事件。 这可能有效,但当我在向导中后退并需要重新订阅事件时,会增加复杂性。

是的,我正在使用Unity。我将我的视图和视图模型注册为实例。它们最初被注册为单例,但当向导重新进入时会导致错误。如果我回到将视图和视图模型注册为单例,则仍需要处理某种视图模型的停用以重置下一次向导的状态。我不知道视图和视图模型的推荐生命周期是多久。 - BenCr
生命周期是根据应用程序的实际情况而定。我会根据逻辑使用两者。你的实例视图模型在“卸载”后仍然处理事件吗?它的~finalizer()是否触发? - Big Daddy
Finalizer不会触发,我怀疑是因为它在GC上触发而不是在对象超出范围时触发。 - BenCr
2
在您的VM上实现IActiveAware接口。您可以在这里查找示例。 - Kapitán Mlíko
@BenCr 好的,我很高兴问题已经解决 :) 你应该提供这个问题的答案 :) - Kapitán Mlíko
显示剩余5条评论
2个回答

6
解决方案是在我的视图模型中实现Microsoft.Practices.Prism.IActiveAware
public bool IsActive
{
    get { return _isActive; }
    set
    {
        if (_isActive != value)
        {
            _isActive = value;
            DoActiveChangedWork(value);
        }
    }
}

public event EventHandler IsActiveChanged;

在视图中实现这个功能也是可行的,但不是必须的。


我不认为它必须在View和VM中都实现。在您的VM中实现完全足够。 IsActive由RegionBehavior设置。您只需检查该值是否为false,然后取消订阅事件即可...就这样:) 如果我错了,请纠正我,而且我会说没有必要触发IsActiveChanged事件,因为没有订阅者需要。 - Kapitán Mlíko
@ViktorLaCroix 我猜可能是这样,但还没有测试过。我也不明白为什么他们在事件定义的末尾使用 = delegate { }; 语法。等我有时间时,我应该用更好的代码示例清理这个答案,并删除链接。 - BenCr

0
如果您正在谈论Prism EventAggregator - 您可以将keepSubscriberReferenceAlive参数设置为false,这样它将在底层使用弱引用,因此当对象“死亡”时,GC会自动取消订阅所有内容。
fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, true);

否则你必须自己明确地取消订阅:

fundAddedEvent.Unsubscribe(FundAddedEventHandler);

我正在使用Prism,抱歉我添加了标签但在问题中没有表述清楚。我原本以为默认行为是使用弱引用。 - BenCr
keepSubscriberReferenceAlive标记没有产生任何效果。已订阅的实例可能不再被引用,但它尚未被垃圾回收,因此事件仍会再次触发。我需要找到一个方法来停用视图模型。 - BenCr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接