您必须创建自己的机制来做到这一点。虽然这不是太糟糕。考虑添加另一个抽象层。例如,一个名为FilteredEventHandler
的简单类可以检查myOpRunning的状态,并调用真实的事件处理函数或抑制事件。类会是这个样子:
public sealed class FilteredEventHandler
{
private readonly Func<bool> supressEvent;
private readonly EventHandler realEvent;
public FilteredEventHandler(Func<bool> supressEvent, EventHandler eventToRaise)
{
this.supressEvent = supressEvent;
this.realEvent = eventToRaise;
}
//Checks the "supress" flag and either call the real event handler, or skip it
public void FakeEventHandler(object sender, EventArgs e)
{
if (!this.supressEvent())
{
this.realEvent(sender, e);
}
}
}
然后,当你挂钩的情况下,这样做:
this.Control.WhateverEvent += new FilteredEventHandler(() => myOpRunning, RealEventHandler).FakeEventHandler;
当WhateverEvent
得到提高,它会调用FilteredEventHandler.FakeEventHandler method
。该方法将检查标志并调用,或者不调用真正的事件处理程序。这在逻辑上与你已经做的非常相似,但检查myOpRunning标志的代码只在一个地方,而不是遍布整个代码。
编辑回答问题的意见:现在
,这个例子是有点不完整的。完全退订该事件有点困难,因为你失去了对所连接的FilteredEventHandler的引用。例如,你不能这样做:
this.Control.WhateverEvent += new FilteredEventHandler(() => myOpRunning, RealEventHandler).FakeEventHandler;
//Some other stuff. . .
this.Control.WhateverEvent -= new FilteredEventHandler(() => myOpRunning, RealEventHandler).FakeEventHandler; //Not gonna work!
因为你连接了一个委托并解除完全不同的委托!当然,这两个委托都是FakeEventHandler方法,但这是一个实例方法,它们属于两个完全不同的FilteredEventHandler对象。
不知何故,您需要获取为解除挂钩而构建的第一个FilteredEventHandler的引用。像这样的工作,但它涉及了一堆FilteredEventHandler对象是大概没有比原来的问题更好的保持跟踪你正在试图解决:
FilteredEventHandler filter1 = new FilteredEventHandler(() => myOpRunning, RealEventHandler);
this.Control.WhateverEvent += filter1.FakeEventHandler;
//Code that does other stuff. . .
this.Control.WhateverEvent -= filter1.FakeEventHandler;
我会做什么,在这种情况下,是让FilteredEventHandler.FakeEventHandler方法将其'this'引用传递给RealEventHandler。这包括改变RealEventHandler的签名,要么采取其他参数:
public void RealEventHandler(object sender, EventArgs e, FilteredEventHandler filter);
或改变其拍摄您创建包含到FilteredEventHandler参考一个EventArgs子类。这是更好的方式来做到这一点
public void RealEventHandler(object sender, FilteredEventArgs e);
//Also change the signature of the FilteredEventHandler constructor:
public FilteredEventHandler(Func<bool> supressEvent, EventHandler<FilteredEventArgs> eventToRaise)
{
//. . .
}
//Finally, change the FakeEventHandler method to call the real event and pass a reference to itself
this.realEvent(sender, new FilteredEventArgs(e, this)); //Pass the original event args + a reference to this specific FilteredEventHandler
现在被调用可以取消本身,因为它有到得到了在它的参数传递正确的FilteredEventHandler对象的引用RealEventHandler。
我最后的建议,虽然是没做任何这个! Neolisk将它钉在评论中。做这样复杂的事情是一个迹象,表明设计存在问题。对于任何未来需要维护这些代码的人来说(即使是你,令人惊讶的是)都很难找出涉及的非标准管道。
通常,当您订阅活动时,您只需执行一次并忘记它 - 特别是在GUI程序中。
禁用您的控件,以便用户*知道*您没有响应。将它们的Enabled属性设置为false。 –
如果你必须处理过度的事件触发,我会首先考虑重新设计。代码中发生错误的地方。你不应该有这个。在确定问题的真正原因之前,做这种管道应该只是一种临时措施。 – Neolisk