Как EventArgs Cancel работает в событии FormClosing? - PullRequest
3 голосов
/ 31 октября 2009

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

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

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

Ответы [ 3 ]

7 голосов
/ 01 ноября 2009

Я думаю, что оригинальный постер может задаться вопросом, что происходит, когда некоторые подписчики устанавливают 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; } 
}
2 голосов
/ 01 ноября 2009

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