删除ViewModel时如何取消订阅事件?

时间:2018-11-13 11:36:34

标签: c# .net

我有一个ViewModel,它有一些事件可以将动作通知给另一个viewModel。

我几乎没有活动,但我会问一个,就是这样:

public event MyEventEventHandler MyEvent;
private void OnMyEvent(MyType param)
{
    MyEventEvent?.Invoke(param);
}

在中间ViewModel中,我关联了第二个视图模型,该模型具有订阅此事件的方法。我这样做:

MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += mySecondViewmodel.handleEvent;

在这种情况下,是要打开一个对话框,所以主视图模型是对话框,第二个视图模型是调用该对话框的对象,因此当我完成打开对话框时,第二个视图模型仍然是根据主ViewModel订阅,垃圾收集器将不会重新收集主ViewModel。

我的疑问是我应该在主ViewModel或中间视图模型中的finally块中取消订阅该事件?

我在考虑是否可以通过某种方式访问​​主ViewModel中的订阅者集合,因此在关闭状态下,我可以执行MyEvent.clear()之类的操作或取消订阅所有事件的方法,而不是取消订阅在中间ViewModel的finally块中一个接一个地

通常,当我关联两个ViewModel时,我想知道取消订阅事件的最佳方法。

谢谢。

1 个答案:

答案 0 :(得分:0)

您不应仅出于能够取消订阅事件的目的而创建IDisposable类型。 IDisposable表示一种类型包含非托管资源或其他IDisposable类型的实例。

如果视图模型已经实现 IDisposable,那么您当然可以取消那里的事件。

如果没有,则可以创建一个CleanUp(或类似方法)并在那里取消订阅。

我为此类事情使用了一种非常简洁的解决方案。我称它们为一次性事件处理程序(或自动取消订阅事件处理程序)。这就是C#7 “本地函数” 的新功能提供帮助的地方。

void IntermediateViewModel_CreateViewModels()
{
    MainViewModel myMainViewmodel = new MyViewModel();
    SecondViewModel mySecondViewModel = new SecondViewModel();
    myMainViewmodel.MyEvent += LocalEventHandler;

    void LocalEventHandler(object sender, EventArgs e)
    {
        // unsubscribe --> no memory leaks!
        myMainViewmodel.MyEvent -= LocalEventHandler;
        mySecondViewmodel.handleEvent(sender, e);            
    }
}

使用这种方法,当MainViewModel.MyEvent触发时,局部函数LocalEventHandler作为事件处理程序执行。您可以立即在该本地函数中取消订阅该事件,这样就不再有引用(没有内存泄漏,可以对视图模型进行GC处理)。

从您的用例中,我了解到您想创建一个对话框视图模型,使用视图显示它,然后立即删除该视图模型。然后,我的样品完全符合您的要求。

相关问题