我有一个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时,我想知道取消订阅事件的最佳方法。
谢谢。
答案 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处理)。
从您的用例中,我了解到您想创建一个对话框视图模型,使用视图显示它,然后立即删除该视图模型。然后,我的样品完全符合您的要求。