"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 чтобы остановить это событие.

Другие вопросы по тегам