FormClosing事件中的EventArgs Cancel是如何工作的?

3
在WinForm的FormClosing事件中,如何使用e.Cancel事件?我知道将其设置为True可以取消关闭,但是在什么时候表单会处理它?该属性是否有任何其他操作?
我该如何在自定义控件中实现类似的操作?(C#或VB)
注意:我已经在Google和SO搜索中寻找了30分钟,但没有找到答案,如果这是一个重复的问题,请谅解。

参见https://dev59.com/50XRa4cB1Zd3GeqPuspA - Robert Harvey
3个回答

7
我认为原帖作者可能想知道当一些订阅者设置Cancel = false而另一些订阅者设置Cancel = true时会发生什么。如果是这种情况,则“表单何时处理此项”这个问题变得更加重要。
起初,我想知道setter是实现OR还是AND每个值。使用Reflector检查CancelEventArgs.Cancel的setter显示它只设置一个私有字段:
public bool Cancel
{
    get{ return this.cancel; }
    set{ this.cancel = value; }
}

我想查看 'Form.OnClosing(CancelEventArgs args)' 的代码,以便确定何时检查该值,就像之前的答案一样,但是反编译器显示的并不是这样:

[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void OnClosing(CancelEventArgs e)
{
    CancelEventHandler handler = (CancelEventHandler) base.Events[EVENT_CLOSING];
    if (handler != null)
    {
        handler(this, e);
    }
}

我启用了源代码调试并发现,从Events集合中获取EVENT_CLOSING委托会深入到窗口API中,因此当表单设置Cancel = true时,OnClosing的第一行中的handlernull,这意味着托管代码实际上从未测试过CancelEventArgs.Cancel == true。如果您想要查看EventHandlerList内部的丑陋细节,可以得到以下内容:

get { 
    ListEntry e = null;
    if (parent == null || parent.CanRaiseEventsInternal) 
    {
        e = Find(key);
    }
    if (e != null) { 
        return e.handler;
    } 
    else { 
        return null;
    } 
}

在调试时,如果关闭操作被取消,parent.CanRaiseEventsInternal的值为false。

因此... 取消窗体关闭的实际实现比先前的答案更复杂,但是关于如何正确取消自己的事件的建议展示了如何在托管代码中进行操作。调用CancelEventHandler,然后测试所有订阅者都有机会将值设置为true之后,CancelEventArgs.Cancel的值。这仍然没有回答如果一些订阅者设置Cancel = false而另一些订阅者设置Cancel = true会发生什么。有人知道吗?是否需要像下面这样做?

public bool Cancel
{
   get{ return this.cancel; }
   set{ this.cancel = this.cancel || value; } 
}

2

按照 Windows Forms 中使用的标准事件生成模式:

public event CancelEventHandler MyEvent;

protected void OnMyEvent(CancelEventArgs e) {
  CancelEventHandler handler = MyEvent;
  if (handler != null) {
    handler(this, e);
  }
}

private void button1_Click(object sender, EventArgs e) {
  CancelEventArgs args = new CancelEventArgs();
  OnMyEvent(args);
  if (!args.Cancel) {
    // Client code didn't cancel, do your stuff
    //...
  }
}

0
function OnMyCancelableEvent()
{
   var handler = CancelableEvent;
   var args = new CancelEventArgs()
   if(handler != null)
   {
        handler(this, args)
        if(args.Canceled)
           // do my cancel logic
        else
           // do stuff
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接