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