Предложить пользователю сохранить при закрытии приложения

StackOverflow https://stackoverflow.com/questions/462903

Вопрос

Я пишу то, что сводится к редактору документов.Когда приложение закрывается, мне нужно предложить пользователю сохранить изменения.Это достаточно просто.Мой вопрос в том, когда уместно не запросите пользователя, а вместо этого просто удалите несохраненные данные и закройте.

В событии FormClosing перечисление CloseReason включает:

  • Нет
  • Windowsшутдаун
  • MDIFORM закрывающий
  • Закрытие пользователя
  • TaskManagerClosing Закрывающий
  • FormOwnerClosing Закрывающий
  • Вызов ApplicationExitCall

Я полагаю, что закрытие WindowsShutDown и TaskManagerClosing не должно приводить к появлению запроса "сохранить изменения?" чтобы предотвратить зависание приложения с отображением этого запроса.

Является ли это стандартной практикой, или я должен делать здесь что-то еще?

Для наглядности, вот код:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);

    if (!(e.CloseReason == CloseReason.WindowsShutDown || e.CloseReason == CloseReason.TaskManagerClosing)
            && this.ChangesPending())
    {
        switch (MessageBox.Show(this, "Save changes?", "Save Changes", MessageBoxButtons.YesNoCancel))
        {
            case DialogResult.Yes:
                this.Save();
                break;
            case DialogResult.No:
                // Do nothing
                break;
            case DialogResult.Cancel:
                e.Cancel = true;
                break;
        }
    }
}
Это было полезно?

Решение

Я думаю, что TaskManagerClosing должна быть единственная причина, которая не запрашивает, если таковая имеется.Лично я хотел бы, чтобы мне подсказали в случае WindowsShutDown.Если я закрываю Windows с несохраненным документом где-то, это означает, что я забыл об этом.

Другие советы

Я бы определенно также показал диалоговое окно "Хотите ли вы сохранить" в WindowsShutDown (приложение может, напримербыли в фоновом режиме в течение некоторого времени, и пользователь забыл об этом, или он, возможно, недолго думая нажал на "Перезагрузку" после установки пакета обновления и т.д.).

Что касается TaskManagerClosing, я бы не стал показывать диалоговое окно в этом случае.

Лично я предпочитаю просто закрывать программу, когда пользователь выбирает закрыть, если во время закрытия есть какие-либо несохраненные документы, я предпочитаю сохранять резервные копии этих файлов и сообщать пользователю о наличии несохраненных документов при следующем открытии приложения.

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

Таким образом, с помощью этого метода вам не нужно беспокоиться о том, было ли закрыто приложение.

На самом деле ближайшая причина - спорный вопрос, не так ли?Тот факт, что ваша форма уходит, - это то, что вы пытаетесь уловить.

Теперь вам нужно знать, обработало ли ваше приложение уже событие "сохранить".Если это так, то форма может исчезнуть.Вы сохранили свой документ.Но если нет, вы можете запросить пользователя.

Если вы можете быстро проверить данные (т.е.выполните сравнение строк или хэшей в документе по сравнению с данными в файле), тогда вы узнаете, сохранил ли пользователь данные формы.

В противном случае, если полей много, и проверка каждого из них требует больших ресурсов, то установите в вашей форме флаг "IsDirty".Пусть метод Save() установит для IsDirty значение false, а каждое другое изменение поля установит для него значение true.

Затем, в FormClosing, все, что вам нужно, это :

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (isDirty) 
    {
        DialogResult R = MessageBox.Show(this, "Save changes?", "Save Changes", 
                MessageBoxButtons.YesNoCancel);

        if (R == DialogResult.Yes)
        {
            this.Save();
        } else if (R == DialogResult.Cancel)
        {
            e.Cancel = true;
        }
    }
}

Я бы подумал, что даже TaskManagerClosing можно было бы использовать подсказку для сохранения.Если ваше приложение реагирует нормально, закрытие его через диспетчер задач не должно отличаться от любого другого способа его закрытия.Если он завис, не имеет значения, что делает ваш обработчик OnClose - он никогда туда не попадет.

Я согласен с @Jerry в том, что более важно избегать запроса на сохранение, если данные не изменились с момента последнего сохранения.Обычно я использую простой флаг "изменено", который устанавливается при любом действии редактирования и снимается при сохранении и загрузке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top