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