"e.Cancel " в форме закрытия мероприятия
При использовании FormClosing
событие, почему код e.Cancel = true;
работать, но new CancelEventArgs().Cancel = true;
не работает?
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
new CancelEventArgs().Cancel = true;
}
4 ответа
Событие вызвано сантехническим кодом Winforms. Единственный способ увидеть, что пользовательский обработчик событий хочет изменить поведение по умолчанию, это e
объект. Создание нового объекта CancelEventArgs не имеет побочных эффектов, которые может обнаружить сантехника.
Есть что-то еще не так, события вызываются в пользу внешнего кода, давая ему знать, что происходит, и давая ему возможность изменить поведение. Здесь нет внешнего кода, обработчик события фактически является частью того же класса, который вызывает событие. Другими словами, форма слушает свои собственные события. Есть гораздо лучший способ справиться с этим, вы переопределяете метод, который вызывает событие. Как это:
protected override void OnFormClosing(FormClosingEventArgs e) {
e.Cancel = true;
base.OnFormClosing(e);
}
Теперь внешний код может переопределить поведение по умолчанию, события возникают после запуска метода OnXxxx. И у вас есть выбор: если вы не хотите, чтобы внешний код переопределял поведение, просто поменяйте местами два оператора.
Я думаю, что код делает именно то, что говорит; чего не хватает, так это буквального прочтения.
Когда вы назначаете новое значение e.Cancel
Вы модифицируете e
это предоставляется в качестве параметра функции. После завершения функции обработчика события это FormClosingEventArgs
Экземпляр, включая любые изменения, внесенные в него из обработчика событий, будет доступен для любого кода, вызвавшего обработчик событий. В данном случае это почти наверняка код Winforms, написанный Microsoft.
С другой стороны, когда вы внутри этого обработчика событий создаете новый экземпляр типа FormClosingEventArgs
и сделать что-то с этим, нет ничего, чтобы предоставить эту информацию обратно вызывающей стороне; вам нужно что-то явное для этого. Поскольку вызывающая сторона смотрит на значение параметра, который она передала после завершения обработчика события, вам нужно как-то заменить содержимое e
как видно вызывающей стороне с вновь созданным экземпляром. В других случаях такой результат может быть предоставлен как возвращаемое значение.
В общем, результат new T()
для какого-то типа T
, является экземпляром типа T
, Таким образом, вы можете работать с результатом выражения new T()
как вы бы ненулевой переменной типа T
, В вашем конкретном случае вы присваиваете значение свойству типа T
(в частности, экземпляр этого типа, созданный таким образом). (Существует особый случай, когда конструктор терпит неудачу, но давайте пока не будем здесь; для простых типов это в значительной степени будет означать, что вы находитесь в таком тяжелом положении, что ваша программа вряд ли сможет продолжить работу в любом случае.)
Здесь важно то, что если вы не назначите результат выражения new T()
В любом месте вновь созданный экземпляр отбрасывается (технически становится недоступным) после завершения инструкции. Затем, в какой-то момент, включается сборщик мусора.NET и фактически освобождает выделенную память. На самом деле это ничем не отличается от размещения переменной в одной функции, вызова этой функции из другой функции и попытки доступа к переменной, выделенной таким образом из второй функции, без каких-либо действий по переносу переменной из первой функции во вторую, кроме как здесь. задействована только одна функция.
Выполнение чего-то вроде вашей второй строки кода в обработчике событий было бы довольно необычно, но в принципе может быть допустимым, если вызов конструктора имеет какой-то побочный эффект, который вы хотите использовать, например, запуск отложенной загрузки.
Этот код обязательно работает, просто проверьте его
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (PreClosingConfirmation() == System.Windows.Forms.DialogResult.Yes)
{
Dispose(true);
Application.Exit();
}
else
{
e.Cancel = true;
}
}
private DialogResult PreClosingConfirmation()
{
DialogResult res = System.Windows.Forms.MessageBox.Show(" Do you want to quit? ", "Quit...", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
return res;
}
Счастливое Кодирование
Это потому что CancelEventArgs
является ссылкой на объект, переданной обработчику события в вашем коде. Код за кулисами поднимается FormClosing
с CancelEventArgs
объект и все обработчики событий получают тот же объект. Как только все обработчики получили свою очередь, закулисный код проверяет CancelEventArgs
объект, который он послал, чтобы увидеть, если его Cancel
свойство установлено в true
, Если это так, он ничего не делает, и FormClose
цепочка событий останавливается. Если Cancel
является false
(CancelEventArgs
значение по умолчанию), то есть оно не установлено Cancel
цепочка событий, закулисный код продолжается, а затем поднимает FormClosed
событие.
Вы можете прочитать больше на Form.FormClosing Event на MSDN.
В Forms
все события -ing обычно сопровождаются событием -ed. События обычно имеют CancelEventArgs
, который может иметь свое Cancel
свойство установлено в true
чтобы остановить это событие.