При разработке функционала в обычных формах разработчики 1С иногда сталкиваются с нетипичным поведением платформы: после проведения документа пользователем и вызова обычного диалогового окна с вопросом система при попытке закрыть форму выдает предупреждение: «Данные были изменены. Сохранить изменения?».
При этом принудительная проверка свойства формы Модифицированность показывает значение Ложь, а сам код внутри обработчика не меняет реквизиты объекта или элементы формы. Рассмотрим подробно, почему возникают подобные ситуации и как правильно реализовать интерактивный диалог с пользователем в событиях формы.
Проанализируем сценарий, при котором возникает эта проблема:
ПослеЗаписи.Вопрос().Причина такого поведения заключается в разрыве цепочки обработки событий модальным окном. Функция Вопрос() блокирует поток выполнения и передает управление внутреннему циклу сообщений. В момент проведения документа на сервере обновляется системная версия объекта и его данные в базе. Вызов синхронного модального окна замораживает процесс штатного закрытия формы. При выходе из модального режима менеджер форм платформы обнаруживает рассинхронизацию контекста закрытия и считает, что данные формы требуют повторного подтверждения сохранения.
Свойство Модифицированность отвечает исключительно за интерактивные изменения элементов пользователем и не отражает внутренние системные флаги завершения команд формы.
Наиболее эффективный и правильный способ решения проблемы — использование асинхронного метода ПоказатьВопрос вместе со специальным объектом ОписаниеОповещения. Это позволяет не прерывать основной поток выполнения платформы: обработчик ПослеЗаписи завершается мгновенно, а форма закрывается штатно без лишних вопросов.
Рассмотрим пример реализации асинхронного вопроса в модуле обычной формы документа:
Процедура ПослеЗаписи(Отказ)
// Формируем описание оповещения для обработки ответа пользователя
Оповещение = Новый ОписаниеОповещения("СоздатьЗаявкуНаДоставкуЗавершение", ЭтаФорма);
// Вызываем немодальный диалог
ПоказатьВопрос(Оповещение, "Создать автоматически ""Заявку на доставку""?", РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Да);
КонецПроцедуры
Процедура СоздатьЗаявкуНаДоставкуЗавершение(Результат, Параметры) Экспорт
Если Результат <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
// Создаем подчиненный документ после подтверждения пользователем
НоваяЗаявка = Документы.ЗаявкаНаДоставку.СоздатьДокумент();
НоваяЗаявка.Заполнить(Ссылка);
ФормаЗаявки = НоваяЗаявка.ПолучитьФорму();
ФормаЗаявки.Открыть();
КонецПроцедуры
Благодаря такому подходу функция ПоказатьВопрос не блокирует поток выполнения программы. Обработчик ПослеЗаписи корректно завершает свою работу, и форма закрывается без появления ложных сообщений о модифицированности.
Если решение о создании связанных документов или выполнении дополнительных действий должно приниматься до момента сохранения данных в базу, логичнее перенести диалоговое окно в событие ПередЗаписью.
В таком случае, если пользователь отказывается от действия или отменяет операцию, мы можем установить флаг Отказ = Истина и предотвратить проведение документа еще до начала транзакции.
Чтобы избежать лишних всплывающих диалогов в процессе записи, проанализируем альтернативный юзабилити-подход: использование флагов на самой форме.
Булево (например, СоздатьЗаявкуНаДоставку).ПослеЗаписи проверяем значение флага и создаем необходимый документ без вызова модальных окон.Этот вариант делает поведение системы полностью предсказуемым и избавляет пользователя от необходимости отвечать на всплывающие вопросы при каждой записи документа.