Разработка и Конфигурация · 9 мин
Как вызвать вопрос «Да/Нет» в 1С
Как вывести диалог с кнопками «Да» и «Нет» в 1С: метод Вопрос, ПоказатьВопрос с оповещением, коды возврата, примеры кода и типичные ошибки разработчика.
Диалог с кнопками «Да» и «Нет» — один из самых частых элементов интерактивной логики в 1С: подтверждение удаления документа, согласие на перезапись файла, запрос перед проведением. Платформа предоставляет два способа вызвать такой вопрос: устаревший модальный метод Вопрос() и современный асинхронный ПоказатьВопрос(). Выбор между ними зависит от режима запуска конфигурации и требований к совместимости.
Ключевая сложность в том, что в тонком и веб-клиенте модальные окна запрещены, поэтому привычный код вида Если Вопрос("Удалить?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда просто не выполнится. Нужно использовать оповещения и разбивать логику на процедуры. Ниже разобраны оба подхода, параметры, коды возврата и типичные ошибки.
Метод Вопрос(): классический модальный вызов
Функция Вопрос() открывает модальное окно и приостанавливает выполнение кода до ответа пользователя. Синтаксис: Вопрос(ТекстВопроса, Кнопки, Таймаут, КнопкаПоУмолчанию, Заголовок, КнопкаТаймаута). Для вопроса «да/нет» достаточно первых двух параметров.
Результат = Вопрос("Удалить выбранный документ?", РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет, "Подтверждение");
Если Результат = КодВозвратаДиалога.Да Тогда
УдалитьДокумент();
КонецЕсли;
Третий параметр — таймаут в секундах, после которого окно закроется само. Четвёртый — кнопка по умолчанию: для деструктивных действий (удаление, отмена проведения) безопаснее ставить КодВозвратаДиалога.Нет, чтобы случайное нажатие Enter не запустило необратимую операцию.
Метод работает только в толстом клиенте обычного приложения и в режиме, где разрешены модальные вызовы. В управляемых формах, тонком и веб-клиенте он вызовет ошибку, если в конфигураторе не включён режим использования модальности — а включать его не рекомендуется, так как современные браузеры блокируют синхронные диалоги.
ПоказатьВопрос(): асинхронный вариант для управляемого приложения
Процедура ПоказатьВопрос() не останавливает выполнение кода: она открывает окно и сразу возвращает управление, а ответ пользователя приходит в отдельную процедуру через объект ОписаниеОповещения. Это обязательный подход для тонкого и веб-клиента.
&НаКлиенте
Процедура УдалитьНажатие(Команда)
Оповещение = Новый ОписаниеОповещения("УдалитьНажатиеЗавершение", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Удалить выбранный документ?", РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет);
КонецПроцедуры
&НаКлиенте
Процедура УдалитьНажатиеЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
УдалитьДокументНаСервере();
КонецЕсли;
КонецПроцедуры
Обратите внимание: процедура-обработчик должна быть экспортной (ключевое слово Экспорт) и располагаться в том же модуле, который указан вторым параметром в ОписаниеОповещения. Если нужно передать в обработчик свои данные, используйте третий параметр конструктора оповещения — произвольное значение, которое придёт в ДополнительныеПараметры.
- 1Создайте команду или кнопку, из которой вызывается вопрос
- 2Сформируйте объект ОписаниеОповещения с именем процедуры-обработчика
- 3Вызовите ПоказатьВопрос с текстом и РежимДиалогаВопрос.ДаНет
- 4Создайте экспортную процедуру-обработчик с параметрами Результат и ДополнительныеПараметры
- 5В обработчике проверьте Результат = КодВозвратаДиалога.Да и выполните действие
- 6Протестируйте в тонком клиенте: окно должно открыться, а код не должен зависнуть
Кнопки, коды возврата и дополнительные режимы
Режим диалога определяет набор кнопок, а результат сравнивается с системным перечислением КодВозвратаДиалога. Для вопросов «да/нет» чаще всего используются три режима.
| Режим | Кнопки | Возможные коды возврата | Когда применять |
|---|---|---|---|
| ДаНет | Да, Нет | Да, Нет | Простое подтверждение без варианта отмены |
| ДаНетОтмена | Да, Нет, Отмена | Да, Нет, Отмена | Когда пользователь может прервать всю операцию |
| ОК | ОК | ОК | Уведомление без выбора (лучше использовать ПоказатьПредупреждение) |
Важный нюанс: если пользователь закрыл окно крестиком или клавишей Esc, при режиме ДаНет результатом будет КодВозвратаДиалога.Нет (или кнопка по умолчанию при таймауте). Поэтому логику стройте так, чтобы отсутствие явного «Да» трактовалось как отказ, а не как согласие.
Передача контекста в обработчик оповещения
Частая задача: в обработчике ответа нужен объект, который был доступен в момент вопроса — ссылка на документ, строка таблицы, структура параметров. Передайте его третьим параметром в конструктор ОписаниеОповещения.
Оповещение = Новый ОписаниеОповещения("ПослеВопроса", ЭтотОбъект, ТекущаяСтрока.Ссылка);
ПоказатьВопрос(Оповещение, "Провести документ?", РежимДиалогаВопрос.ДаНет);
В обработчике значение придёт вторым параметром. Если контекст не нужен, дополнительные параметры будут равны Неопределено — учитывайте это, чтобы не получить обращение к свойству пустого значения.
Типичные ошибки и ограничения
Самая распространённая ошибка — ожидание, что код после ПоказатьВопрос выполнится после ответа пользователя. На деле он выполняется немедленно, до ответа. Всю зависимую логику нужно переносить внутрь процедуры-обработчика.
Вторая ошибка — вызов вопроса на сервере. Диалоги доступны только в клиентском контексте (директивы &НаКлиенте). Вызов на сервере приведёт к ошибке компиляции или выполнения. Если решение зависит от серверных данных, получите их заранее и передайте в клиентскую процедуру.
Третья группа проблем — неэкспортная процедура-обработчик, опечатка в её имени (платформа сообщит об ошибке только в момент ответа пользователя) и забытой проверке результата на Неопределено при закрытии окна по таймауту в некоторых сценариях.
Проверка результата и отладка
Для проверки добавьте временный вывод в обработчик: Сообщить("Результат: " + Результат);. Убедитесь, что при каждом способе закрытия окна (кнопка «Да», «Нет», крестик, Esc, истечение таймаута) логика ведёт себя предсказуемо.
Как проверить результат
В обработчик приходит КодВозвратаДиалога.Да, действие выполняется
Обработчик не вызывается или результат Неопределено
Действие не выполняется, ошибок нет
Выполняется деструктивное действие или падает исключение
Срабатывает кнопка по умолчанию, логика отказа
Окно висит бесконечно или таймаут трактуется как согласие
Полезно также проверить поведение в разных клиентах: тонком, толстом и веб-клиенте, если конфигурация в них работает. Асинхронный вариант через ПоказатьВопрос корректен во всех режимах, тогда как модальный Вопрос() требует специальных настроек и считается устаревшим.
Что важно запомнить
Для обычного приложения подходит функция Вопрос() с РежимДиалогаВопрос.ДаНет. Для управляемых форм, тонкого и веб-клиента используйте ПоказатьВопрос с ОписаниеОповещения и экспортной процедурой-обработчиком. Результат сравнивайте с КодВозвратаДиалога.Да, кнопку по умолчанию для опасных действий ставьте «Нет», а зависимый код размещайте только внутри обработчика.
Частые вопросы
Можно ли изменить текст кнопок «Да» и «Нет» на свои варианты?
Стандартные режимы диалога имеют фиксированные подписи. Если нужны произвольные кнопки, сформируйте список значений с собственными элементами и передайте его вместо РежимДиалогаВопрос — результатом будет значение выбранного элемента списка.
Почему код после ПоказатьВопрос выполняется до ответа пользователя?
Это особенность асинхронной модели: метод лишь ставит показ окна в очередь и сразу возвращает управление. Ответ обрабатывается позже в процедуре оповещения. Всю логику, зависящую от ответа, переносите в обработчик.
Что вернёт диалог, если пользователь закроет окно крестиком?
При режиме ДаНет закрытие окна обычно трактуется как отрицательный ответ (КодВозвратаДиалога.Нет). Поэтому проектируйте логику так, чтобы любой исход, кроме явного «Да», означал отказ от действия.
Работает ли Вопрос() в веб-клиенте?
Нет, модальные вызовы в веб-клиенте блокируются, и метод Вопрос() завершится ошибкой, если не включён режим модальности. Правильное решение — асинхронный ПоказатьВопрос с описанием оповещения.
Как задать заголовок окна вопроса?
Пятый параметр обоих методов — заголовок диалога: ПоказатьВопрос(Оповещение, "Текст", РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет, "Подтверждение операции"). Если параметр опущен, выводится стандартный заголовок платформы.
Можно ли вызвать вопрос из серверной процедуры?
Нет, интерактивные диалоги доступны только в клиентском контексте. Получите нужные данные на сервере заранее, верните их на клиент и уже там вызовите ПоказатьВопрос.