在 ViewModel 中取消挂钩事件处理程序的正确方法是什么

What is the correct way to Unhook event Handlers in a ViewModel

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

假设我有一个 View 模型,如下所示:

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

但是当我想到时并没有被调用。这似乎是不稳定的,有时甚至根本不打电话?所以我决定搜索 "When does dispose get called" ,这导致我 this link 解释说 DisposeFinaliser / Destructor

调用

让我进入最后一项研究的是,我记得有人说不要在 Destructor 中解开事件处理程序,因为它永远不会被调用,从 this link.

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

我可能建议转换为 ObservableCollection,因为 ViewModel 的原因是要绑定一些东西。然后,您可以直接在 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();
        }
    }
}

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

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

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