在哪里取消订阅活动?

Sin*_*atr 5 c# events

例如,对于一般类型,它在构造函数中订阅一些事件:

class SomeType
{
    public SomeType(...)
    {
        someEvent1 += ...
        someEvent2 += ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我在哪里取消订阅活动?

  • 终结器?
  • IDisposable
  • 一些方法DontForgetToCallMeSoICanUnsubscribeFromEvents()
  • 使用弱事件模式?

我知道这要看情况。对于控件(wpf、winforms),有一些事件可用于订阅/取消订阅,例如Loaded/ UnloadedHandleCreated/HandleDestroyed等。但是如果父级是一个简单的怎么办object

还有一些更具体的示例:嵌套 ViewModel,其中每个级别都是一个List<NextLevelVM>,在任何级别 ViewModel 都可以被删除,这是否意味着每个 ViewModel 必须实现IDisposable(如果是正确的方式)它调用Dispose列表中的每个项目?我尝试使用弱事件,但效果并不好

Ada*_*m B 0

我发现处理这个问题的一个非常好的方法是在页面的代码后面创建两个方法,调用 ViewModel 上的方法来启动/停止侦听事件,具体取决于事件是否可见。

下面我使用了 Appearing 函数,但根据您使用的框架,它可能会略有不同,但该策略应该有效。

在页面类中:

protected override void OnAppearing()
{
    base.OnAppearing();
    _myViewModel.StartListeningToEvents();
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    _myViewModel.StopListeningToEvents();
}
Run Code Online (Sandbox Code Playgroud)

然后在我的 ViewModel 中,我实际上订阅了我需要的事件:

public void StartListeningToEvents()
{
    SomeProperty.PropertyChanged += PropertyUpdated;
}

public void StopListeningToEvents()
{
    SomeProperty.PropertyChanged -= PropertyUpdated;
}

void PropertyUpdated(object sender, PropertyChangedEventArgs e)
{
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

我的示例是属性更改事件。但类似的代码应该适用于任何事件。

通过这种方式,您可以保证页面仅在打开时侦听事件,并且除了在页面不再打开时调用一个事件之外,您无需担心处理任何事情。