使用某些参数删除匿名事件处理程序

时间:2012-05-16 14:18:48

标签: c# events event-handling

我订阅了这样的活动:

private void CoupleOverlay(IMapVisual mapVisual)
{            
      overlay.DrawTilesProgressChanged += (s, e) => 
      {               
          mapVisual.DrawingProgress = e.ProgressPercentage;
      };
}

应用程序可能多次调用CoupleOverlay事件,因此我需要取消订阅DrawTilesProgressChanged事件并再次订阅,但因为它是匿名事件,所以我无法取消订阅它。我试图转换为

private void CoupleOverlay(IMapVisual mapVisual)
{
    overlay.DrawTilesProgressChanged -=overlay_DrawTilesProgressChanged;                 
    overlay.DrawTilesProgressChanged +=overlay_DrawTilesProgressChanged;                 
}

private void overlay_DrawTilesProgressChanged(object sender, DrawTilesProgressChangedTileOverlayEventArgs e)
{       
    mapVisual.DrawingProgress = e.ProgressPercentage;
}

它不起作用,因为mapVisualoverlay_DrawTilesProgressChanged方法上不是有效变量。

如果我将代码更改为

private void CoupleOverlay(IMapVisual mapVisual)
{
    EventHandler<DrawTilesProgressChangedTileOverlayEventArgs> drawEvent = (s, e) =>
    {           
        mapVisual.DrawingProgress = e.ProgressPercentage;
    };

    overlay.DrawTilesProgressChanged -= drawEvent;
    overlay.DrawTilesProgressChanged += drawEvent;
}

它不起作用因为drawEvent是一个局部变量,下次我调用CoupleOverlay时,它会创建一个新的。

那么如何取消订阅此事件处理程序?或者我怎么知道我订阅了这个活动所以我不需要再次订阅?

2 个答案:

答案 0 :(得分:1)

  

它不起作用,因为drawEvent是局部变量,下次我调用CoupleOverlay时,它会创建一个新的。

事实上。您基本上需要保留实例变量而不是局部变量。实例变量实际上是“当前订阅的事件处理程序”。然后在CoupleOverlay中删除该事件处理程序,创建一个新事件(将其存储在变量中)并重新订阅它。

另一种方法是使用单个事件处理程序,但保留“当前”覆盖并将可视化映射为事件处理程序使用的实例变量。然后CoupleOverlay方法只需要更新这些变量。

答案 1 :(得分:1)

  

如何取消订阅此事件处理程序

你不能因为lambda是一个局部变量,并且不能在声明它的范围之外(在函数本身,在你的情况下)。要获得所需的灵活性,您需要使用delegates

  

我怎么能理解我订阅和活动所以我不需要   再次订阅

要获得子列表,就足以使用:

MulticastDelegate.GetInvocationList Method(事件和代理是多播的)