Как EventArgs Cancel работает в событии FormClosing?

Как работает событие e.Cancel в событии FormClosing в WinForm? Я знаю, что вы установили его на True отменить закрытие, но в какой момент форма обрабатывает это? Есть ли вторичные действия, предпринятые собственностью?

Как я могу реализовать подобное действие в пользовательском элементе управления? (C# или VB)

Примечание: я искал около 30 минут и не смог найти ни одного ответа в Google или поиске SO, так что, если это дубликат, мой плохой.

3 ответа

Решение

Я думаю, что оригинальный постер может задаваться вопросом, что происходит, когда некоторые подписчики устанавливают Cancel = false и некоторые подписчики установлены Cancel = true, Если это так, то вопрос "когда эта форма обрабатывает" приобретает большую важность.

Сначала я задавался вопросом, был ли установлен сеттер для ИЛИ или И для каждого значения. Использование Reflector для проверки правильности установки CancelEventArgs.Cancel показывает, что он просто устанавливает приватное поле:

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

Поэтому я подумал, что заглянуть в "Form.OnClosing(CancelEventArgs args)" можно будет увидеть, когда проверяется значение, как и в предыдущих ответах, но это не то, что показывает Reflector:

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

Так что я включил отладку исходного кода и нашел получение EVENT_CLOSING делегат от Events Коллекция падает глубоко в оконный API, так что handler в первой строке OnClosing является null когда форма устанавливает Cancel = trueЭто означает, что управляемый код никогда не проверяет 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 ложь, если закрытие было отменено.

Итак... фактическая реализация отмены закрытия формы сложнее, чем предыдущие ответы, но их предложения о том, как правильно отменить собственные события, показывают, как это сделать в управляемом коде. Вызовите CancelEventHandler и затем проверьте значение CancelEventArgs.Cancel после того, как все подписчики имели возможность установить значение true, Это все еще не отвечает, что происходит, если некоторые подписчики установлены Cancel = false и какой-то набор Cancel = true, Кто-нибудь знает? Требуется ли что-то вроде следующего?

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

Следуя стандартному шаблону генерации событий, используемому в 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
    //...
  }
}
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
   }
}
Другие вопросы по тегам