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