【问题标题】:Make View Models activation aware in Prism/Composite MVVM WPF application在 Prism/Composite MVVM WPF 应用程序中使视图模型激活感知
【发布时间】:2013-01-31 10:14:36
【问题描述】:

在我的 MVMC 应用程序中,我有一个包含多个步骤的流程,基本上是一个向导。

我的控制器解析了我的外部视图(称为WizardView)并将其添加到主区域。

WizardView 包含一个显示向导进度的面包屑路径和一个用于加载其他视图的子区域(称为WizardRegion)。 Step1View 是加载到WizardRegion 中的第一个视图。

每个视图都使用 Unity 容器将其 ViewModel 注入到构造函数中。

WizardViewModel 订阅多个事件聚合事件,这些事件由步骤视图模型发布。

随着每个步骤的完成,视图模型会发布一个事件,WizardViewModel 使用该事件来存储状态,这意味着WizardViewModel 正在收集每个步骤的数据。步骤 ViewModel 还调用控制器将下一步加载到WizardRegion

在最后一步,WizardViewModel 保存向导的结果,MainRegion 被导航回其他屏幕。

下次进入向导时,我们会创建所有视图和 ViewModel 的新实例,但上一个向导中的事件订阅仍然存在。

如何让我的视图模型知道它们已停用,以便我可以取消订阅我的事件?

另一种选择是取消订阅事件处理程序中的事件。这可能会起作用,但当我退回向导并需要再次重新订阅事件时会增加复杂性。

【问题讨论】:

  • 看起来您正在使用 Unity 进行 DI。真的吗?如果是这样,您是将您的类注册为实例还是单例?
  • 是的,我正在使用 Unity。我正在将我的视图和视图模型注册为实例。它们最初被注册为单例,但是当重新进入向导时它会导致错误。如果我返回将视图和视图模型注册为 Singltons,那么我仍然需要在视图模型中处理某种取消激活,以便下次在向导周围重置状态。我不知道视图和视图模型的推荐生命周期是多少。
  • 生命周期对应用来说是有意义的。我根据逻辑使用两者。您的实例视图模型在“卸载”后是否仍处理该事件?它的 ~finalizer() 会触发吗?
  • 我没有终结器,我会试一试并告诉你。
  • 在你的虚拟机上实现IActiveAware 接口。您可以查看例如here

标签: wpf mvvm prism eventaggregator


【解决方案1】:

解决方案是在我的视图模型中实现Microsoft.Practices.Prism.IActiveAware

public bool IsActive
{
    get { return _isActive; }
    set
    {
        if (_isActive != value)
        {
            _isActive = value;
            DoActiveChangedWork(value);
        }
    }
}

public event EventHandler IsActiveChanged;

也可以在视图中实现这一点,但这不是必需的。

【讨论】:

  • 我不认为它必须在 View 和 VM 中都实现。在你的虚拟机中实现它就足够了。 IsActive 由 RegionBehavior 设置。您只需检查该值是否为假,然后您取消订阅您的事件......只是说':) 如果我错了,请纠正我,而且我会说没有必要触发 IsActiveChanged 事件,因为不需要订阅者。
  • @ViktorLaCroix 我猜可能是这种情况,但还没有测试过。我也不明白他们为什么在事件定义的末尾使用 = delegate { }; 语法。我应该用一个更好的代码示例来清理这个答案,并在我有时间的时候删除链接。
【解决方案2】:

如果您在谈论 Prism EventAggregator - 您可以将 keepSubscriberReferenceAlive 参数设置为 false,这样它将在后台使用弱引用,因此当对象“死亡”时,GC 会自动“取消订阅”所有内容。

fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, true);

否则您必须通过明确退订自己来完成:

fundAddedEvent.Unsubscribe(FundAddedEventHandler);

【讨论】:

  • 我正在使用 Prism,抱歉,我添加了标签,但没有在问题中明确说明。我的印象是默认行为是使用弱引用。
  • keepSubscriberReferenceAlive 标志没有任何效果。订阅的实例可能不再被引用,但它没有被垃圾收集,因此事件仍然会再次触发。我需要找到一种方法来停用视图模型
猜你喜欢
  • 2010-12-04
  • 2018-10-01
  • 1970-01-01
  • 2012-02-11
  • 2011-11-21
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多