代码之家  ›  专栏  ›  技术社区  ›  Álvaro García

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

  •  1
  • Álvaro García  · 技术社区  · 7 年前

    我有一个viewmodel,它有一些事件通知其他viewmodels的操作。

    我没有什么事,但我要问一件事,那就是:

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

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

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

    在本例中,它是打开一个对话框,因此主视图模型是对话框,第二个视图模型是调用对话框的视图模型,所以当我完成打开该对话框时,第二个视图模型如何仍然被分包到主视图模型,垃圾收集器将不会重新调用主视图模型。

    我怀疑我应该在哪里取消订阅事件,在主视图模型的disponse中还是在中间视图模型的finally块中?

    我在想是否有办法访问主视图模型中的子脚本集合,因此在dipose中,我可以执行MyEvent.clear()或类似的操作来取消订阅所有事件,而不是在中间视图模型的finally块中逐个取消订阅所有事件。

    一般来说,当我关联两个视图模型时,我想知道取消订阅事件的最佳方式。

    谢谢。

    1 回复  |  直到 7 年前
        1
  •  1
  •   dymanoid    7 年前

    你不应该做一个类型 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 作为事件处理程序执行。您可以在本地函数中立即取消订阅事件,这样就不再有引用(没有内存泄漏,视图模型可以被gced)。

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

    推荐文章