【问题标题】:What is the correct way to Unhook event Handlers in a ViewModel在 ViewModel 中取消挂钩事件处理程序的正确方法是什么
【发布时间】:2016-02-03 23:16:32
【问题描述】:

所以我一直在研究如何从我的视图模型中正确解除事件处理程序以防止内存泄漏。

假设我有一个像这样的视图模型

class MyViewModel
{
    private List<MyObject> _myObjects;
    public List<MyObject> MyObjects
    {
        get { return _myObjects; }
        set { _myObjects = value; }
    }

    public MyViewModel()
    {
        for (int i = 0; i < 10; i++)
        {
            var obj = new MyObject();
            obj.MySampleEvent += Obj_MySampleEvent ;
        }
    }

    private void Obj_MySampleEvent (object sender, EventArgs e)
    {
        //do something
    }
}

现在最初我找到了This link,其中说实现IDisposable 并添加Dispose 方法:

public void Dispose()
{
   foreach (var obj in MyObjects)
   {
       obj.MySampleEvent -= Obj_MySampleEvent;
   }
}

但是当我想到时,这并没有被调用。它似乎是不稳定的,有时甚至根本没有打电话?所以我决定搜索“什么时候被调用”,这导致我找到this link,解释说DisposeFinaliser/Destructor调用

让我进行最后一项研究的原因是,我记得有人说不要在 Destructor 中取消挂钩事件处理程序,因为它永远不会被从 this link 调用。

所以我只是想最后澄清一下。在 ViewModel 中解开事件处理程序的正确方法是什么?

【问题讨论】:

  • 我猜这取决于您的应用程序的架构。我的虚拟机有一个清理功能,我用它来清理它,它会在我需要时手动调用,然后我在应用程序关闭时循环遍历所有注册的视图模型并清理它们。
  • 内存泄漏?您无需取消订阅。从列表中删除对象,失去 _myObjectMyViewModel 引用的实例就足够了,不会导致任何内存泄漏。

标签: c# events mvvm eventhandler


【解决方案1】:

我通常在导航期间在我的视图模型上取消注册事件处理程序。

例如,当引发 OnNavigatedFrom 事件时(在您的视图上),您可以取消注册当前视图模型上的事件处理程序。然后,当引发 OnNavigatedTo 事件时,您可以重新注册事件处理程序。

关于 IDisposable,我不确定。 我认为 IDisposable 是用于管理资源而不是业务逻辑。

【讨论】:

  • 这是有道理的。我想IDisposable 的出现是因为理想情况下您的视图不想知道要调用UnregisterEvents 的视图模型,所以您需要一个Interface,它导致已经有一个接口IDisposable,它有一个Dispose 方法.所以这可能就是人们建议它的原因
【解决方案2】:

我是否建议将 ViewModel 转换为 ObservableCollection 的原因是要绑定一些东西。然后,您可以直接在 ViewModel 属性上订阅任何事件,这将允许您订阅 Window_Closing 并在该事件中进行清理。

class MyViewModel
{
    private ObservableCollection<MyObject> _myObjects;

    public ObservableCollection<MyObject> MyObjects
    {
        get { return _myObjects; }
        set { _myObjects = value; }
    }

    public MyViewModel()
    {
        for (int i = 0; i < 10; i++)
        {
            var obj = new MyObject();
        }
    }
}

【讨论】:

  • 我的问题 VM 只是帮助解释问题的一个示例。我的实际情况比这更复杂,所以虽然这是正确的,但我理解使用ObservableCollection 的重要性,它实际上不是问题的答案
  • 我的问题是您为什么要使用 INotifyPropertyChanged 而不是在“ViewModel”对象上实现它?当然你也可以实现它并重定向 obj.PropertyChanged。
  • 我不是……这是一个例子!让我将要连接的事件更改为 MySampleEvent 以停止混淆。关键是无论你加入什么事件,你仍然需要处理它
  • 您刚刚回答了自己的问题,损害了我的声誉,因为您的示例表明您正在尝试使用视图模型并进行绑定。
猜你喜欢
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
  • 2012-03-31
  • 1970-01-01
相关资源
最近更新 更多