Должен ли я использовать событие закрытия или переопределять OnClosing?

У меня есть проект WPF, в котором у меня есть окно с пользовательской логикой Close. Я хочу, чтобы какой-то код запускался, когда пользователь закрывает окно. Я знаю два способа сделать это, и мне интересно, что лучше:

Вариант 1) Обработать событие base.Closing.

Вариант 2) Переопределите метод OnClosing.

Вот пример кода:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        base.Closing += this.MainWindow_Closing;
    }

    //Option 1
    void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        //close logic here, or
    }

    //Option 2
    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        //close logic here

        base.OnClosing(e);
    }
}

Единственное отличие, которое я могу найти между двумя вариантами, - косметическое. Мне нравится вариант 2 лучше, потому что он просто выглядит чище для меня. Я предпочитаю переопределять методы обработки событий.

Существуют ли другие различия между этими двумя параметрами? Я знаю, что Option 1 предоставляется для какого-либо другого класса для обработки этого окна. Закрытие события.

Изменить: я забыл упомянуть, что я использую .Net 4.0. Похоже, что .Net 4.5 имеет событие OnFormClosing, которое отменяет событие OnClosing. Я не использовал событие OnFormClosing.

Ответ 1

Основное отличие заключается в переопределении, которое вы определяете при вызове базового кода. Когда вы потребляете событие, вы не контролируете его. Когда вы потребляете событие, вы, по сути, базовый код.

Это важная разница порой, потому что, если есть потребители события, но вам нужно выполнить работу до того, как они будут вызваны, тогда вам нужно переопределить.

В этом случае - вероятно, не большая разница.

Ответ 2

Класс, слушающий его собственные события, немного глуп. Тем не менее, как работают дизайнеры, они были написаны для генерации назначения обработчика события вместо автоматического генерирования переопределения метода. Поскольку вы не используете конструктор и не записываете назначение обработчика событий самостоятельно, вам обязательно нужно одобрить переопределение. Еще одна вещь, которую вы можете сделать неправильно, вы не можете забыть написать задание.

Это действительно имеет значение, если вы (или другой программист) извлекаете класс из вашего класса MainWindow. Теперь у вас есть выбор, как написать свой метод OnClosing():

  • добавьте свой код перед вызовом base.OnClosing(). Вы разрешаете производному классу изменять принятое вами решение. Другими словами, для этого события программист мог заставить e.Cancel вернуться к false. Это нормальный путь.

  • сначала вызовите base.OnClosing(), затем добавьте свой код. Это ставит вас под жесткий контроль без возможности переопределения вашего производного класса. Вы делаете это, когда ваше решение имеет большее значение и/или производный класс не может правильно отменить ваш выбор, возможно, потому что только у вас есть доступ к частной информации.

  • не вызывать base.OnClosing(). Это предотвращает видимость происходящего. Это можно сделать, если вы решительно измените обработку событий. Для этого события, например, когда вы отмените закрытие и, скажем, спрячьте окно.

Ответ 3

Когда вы переопределяете OnClosing, вы можете реализовать логику отмены закрытия (см. MSDN) с помощью CancelEventArgs. См. Также пример.

В случае события вы просто выполняете какую-либо работу до того, как окно будет закрыто, и вы не сможете повлиять на процесс закрытия.