【问题标题】:Using Silverlight MVVM with Prism/Unity, and need to detect when view is closed将 Silverlight MVVM 与 Prism/Unity 一起使用,并且需要检测视图何时关闭
【发布时间】:2010-12-17 11:58:28
【问题描述】:

我正在使用 MVVM(模型-视图-视图模型)模式编写应用程序,并利用 Microsoft P&P 团队的 Prism 和 Unity 位。

我有一个包含项目列表的视图。这些项目包含在 ViewModel 中的 ObservableCollection 中,View 中的列表框数据绑定到该 ViewModel(ViewModel 设置为 View 的 DataContext)。在 ViewModel 中,我运行了一个计时器,它每 30 秒触发一次服务器轮询以获取新数据。当数据返回时,我将其编组到 UI 线程并将新数据添加到 ObservableCollection。这一切都很好。

我遇到的问题是我需要在视图关闭时停止计时器。我不确定要在这里观看什么活动。 Unity 中有什么东西会告诉我该区域的视图何时被替换?是否有一个事件最适合从视图中使用,并且可能将该事件(或外观)传递给 ModelView? My View 是每个 P&P 示例的 UserControl。我找不到“卸载”事件,也找不到覆盖的方法。

我已经在考虑编写自己的服务来处理视图更改(RegionManager 的某种外观),并且可能只是在我的视图上实现一个公共接口来进行清理或在它们从视图中删除时实现 IDisposable看法。但是,如果在核心 Silverlight 框架或 Unity/Prism 的范围内有一种干净的方式来做到这一点,我更愿意走这条路。

编辑 - 答案:

我最终只是通过选择最接近我为我的解决方案所做的事情来标记安德森艾姆斯的答案。但实际上,我也使用了来自 PL 和 GraemeF 的部分,并且对每个人都投了赞成票。这对我来说是一个很好的回应,因为它让我对区域有了更好的了解,给了我另一个框架来查看,并验证了我可能正在走正确的道路,实现一个服务来处理视图更改,而不是仅仅调用进入 RegionManager。

【问题讨论】:

    标签: c# silverlight mvvm prism


    【解决方案1】:

    Caliburn 用其IPresenter Component Model 解决了 Prism 缺失的部分,并且与 Prism 配合得很好。您将在 ViewModel 上实现 IPresenter 接口(或更可能使用基类之一),并在 OnShutdown 和/或 OnDeactivate 中停止计时器。

    您可以自己使用 Caliburn,也可以看看它是如何实现的。

    【讨论】:

    • 现在正在研究 Caliburn。有趣的是,您推荐了一个带有演示者的框架,因为我之前已经做过 MVP(自己开发的框架),所以实际上我就是这样称呼我的 ViewModel 类的。
    【解决方案2】:

    我遇到了这个确切的问题,最终基本上为此创建了一个界面:

    public IApplicationEvents
    {
         void OnClose();
    }
    

    我集中了我的关闭视图代码,基本上只是在删除视图之前寻找这个界面。如果它在那里,我可以调用它(如果它是 UIElement,我检查了 View 本身和 DataContext 属性)。

    我使用附加属性和 EventAggregator 对其进行了一些修饰,但这是基本思想,并且效果很好。

    当您查看关闭时,您需要将其关闭是正确的,尤其是在您使用 DispatcherTimer 时(您应该这样做)。如果你不这样做,这会导致一些非常糟糕的内存泄漏。

    【讨论】:

    • 我实际上是在使用 System.Threading.Timer。作为依赖注入的一部分,我传递了一个 IDispatchBroker,它只是我编写的一个执行线程调度的接口。当应用程序引导此依赖项以使用仅调用 RootVisual 调度程序的非常简单的外观时。当我进行单元测试时,我设置了一个模拟 IDispatcherBroker,它直接调用而不是使用 UI 执行整个“BeginInvoke”操作。我将此 IDispatchBroker 传递到运行计时器的代码中。轮询的数据返回并被分派到 UI。
    • 只是出于好奇,您为什么不使用 IDisposable 而不是创建自己的界面?是否因为 IDisposable 的语义假设非托管资源正在使用中(这仍然可能适用,但并非总是如此)?
    • 对。我通常认为 IDisposable 用于收集非托管资源。这里并非总是如此。
    • 对不起,我没有回复你。实际上,这不是我的完整界面,并且在那里有 OnClose。我想我应该让我的接口继承自 IDisposable。这是一个很好的观点。
    【解决方案3】:

    我认为您正在寻找的是来自 Region Manager 框架的 IActiveAware 接口(请参阅 RegionActiveAwareBehavior):

    RegionActiveAwareBehavior 负责通知视图是否处于活动状态。视图必须实现 IActiveAware 才能接收这些更改通知。这种主动感知通知是单向视图;视图不能通过更改 IActiveAware 界面上的 active 属性来影响其活动状态。

    【讨论】:

    • 如果视图关闭,它不会通知您,只有当它处于活动状态时才会通知您。
    • 可能对我有用。当窗口处于活动状态和非活动状态时,我可以激活和停用我的计时器。我可能会将此与编写我自己的区域经理结合起来,类似于安德森给出的答案。
    • 对,这个想法是尽管您在删除视图之前先停用视图,从而使视图有机会执行它可能需要执行的任何停用任务。如果由于某种原因要求太多,那么 Region 类上的 Remove 方法是虚拟的会有所帮助。因此,很容易扩展它并覆盖 Remove 方法,以便视图将在 Remove 时自动停用。
    • 您也可以从 tabcontrols/etc 获得激活停用事件。
    猜你喜欢
    • 2011-10-06
    • 2017-06-08
    • 2011-11-14
    • 2011-05-03
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多