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