К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как оповестить форму в 1С: методы, обработчики и примеры

Как оповестить форму в 1С: методы Оповестить и ОповеститьОбИзменении, обработчики ОбработкаОповещения и ОбработкаЗаписиНового, примеры кода и типичные ошибки.

При разработке на управляемых формах 1С часто возникает задача: одна форма должна сообщить другой, что произошло событие — записан элемент справочника, выбрано значение, изменился документ. Для этого в платформе предусмотрен механизм оповещений: методы Оповестить(), ОповеститьОбИзменении() и соответствующие обработчики событий формы.

Механизм работает внутри одного клиентского сеанса: оповещение доставляется всем открытым формам, которые подписаны на него через обработчик ОбработкаОповещения. Это не сетевое взаимодействие и не межсеансовый обмен — отправить сообщение другому пользователю таким способом нельзя.

Ниже разобраны основные сценарии: оповещение о записи объекта, передача произвольного события с параметрами, оповещение о выборе из формы подбора, а также способы проверить, что механизм работает, и типичные ошибки, из-за которых форма «не слышит» оповещения.

Как устроен механизм оповещений в 1С

Оповещение — это широковещательное сообщение внутри клиентского сеанса. Любая открытая форма может его отправить, и все открытые формы, у которых определён обработчик ОбработкаОповещения, его получат. Формы без обработчика оповещение просто игнорируют.

Сообщение состоит из трёх частей: имени события (строка, которую разработчик выбирает сам), параметра (произвольное значение, чаще всего ссылка или структура) и источника (значение, позволяющее понять, кто отправил оповещение). Все три элемента доступны в обработчике получателя.

Важное ограничение: оповещения живут только в рамках текущего сеанса и не сохраняются. Если форма-получатель была закрыта в момент отправки, она ничего не получит. Для межсеансового взаимодействия используются другие механизмы — фоновые задания, регистры сведений, система взаимодействия.

ОповеститьОбИзменении: стандартное уведомление о записи объекта

Самый частый сценарий — сообщить системе, что объект записан или изменён, чтобы все открытые динамические списки и формы, показывающие этот объект, обновились. Для этого служит метод ОповеститьОбИзменении(Ссылка).

Динамические списки с основной таблицей подписаны на такие оповещения автоматически: если список отображает справочник «Номенклатура», а вы вызвали ОповеститьОбИзменении(СсылкаНаЭлемент), список обновится без единой строки дополнительного кода. То же происходит при стандартной записи элемента из его формы — платформа сама рассылает оповещение об изменении.

Вручную метод нужен, когда объект записывается программно, минуя форму: например, в обработке группового изменения реквизитов или при загрузке данных из файла. Без вызова ОповеститьОбИзменении открытые списки покажут устаревшие данные до ручного обновления.

&НаКлиенте

Процедура ПослеЗагрузкиДанных(Команда)

ИзмененныеСсылки = ЗагрузитьДанныеНаСервере();

Для Каждого Ссылка Из ИзмененныеСсылки Цикл

ОповеститьОбИзменении(Ссылка);

КонецЦикла;

КонецПроцедуры

Оповестить: передача произвольного события между формами

Когда нужно передать не факт изменения объекта, а произвольное событие — «подбор завершён», «настройки изменены», «пользователь подтвердил действие» — используется метод Оповестить(ИмяСобытия, Параметр, Источник).

Имя события — произвольная строка. Принято давать осмысленные имена, например "ИзмененыНастройкиОтчета" или "ЗаписанПартнер". В параметре передают данные: ссылку, структуру с деталями, массив. В источнике обычно передают саму форму (ЭтаФорма) или уникальный идентификатор формы, чтобы получатель мог отличить «своё» оповещение от чужого.

&НаКлиенте

Процедура ПрименитьНастройки(Команда)

ПараметрыСобытия = Новый Структура;

ПараметрыСобытия.Вставить("Период", ПериодОтчета);

ПараметрыСобытия.Вставить("Склад", ВыбранныйСклад);

Оповестить("ИзмененыНастройкиОтчета", ПараметрыСобытия, ЭтаФорма);

КонецПроцедуры

В форме-получателе обработчик выглядит так:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ИзмененыНастройкиОтчета" Тогда

ЗаполнитьНастройки(Параметр);

СформироватьОтчет();

КонецЕсли;

КонецПроцедуры

Оповещение о выборе из формы подбора

Классический сценарий: из документа открывается форма подбора номенклатуры, пользователь выбирает позиции, и документ должен их получить. Есть два подхода — через ОповеститьОВыборе и через описание оповещения о закрытии.

Способ 1: ОповеститьОВыборе

Метод ОповеститьОВыборе(ВыбранноеЗначение) вызывается в форме подбора. Оповещение получает только та форма, которая открыла подбор, — если она открыла её с указанием владельца или через ОткрытьФорму с последующей обработкой выбора. В форме-владельце срабатывает обработчик ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора).

// В форме подбора

&НаКлиенте

Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;

ОповеститьОВыборе(Элементы.Список.ТекущиеДанные.Ссылка);

КонецПроцедуры

// В форме документа

&НаКлиенте

Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

НоваяСтрока = Объект.Товары.Добавить();

НоваяСтрока.Номенклатура = ВыбранноеЗначение;

КонецПроцедуры

Способ 2: ОписаниеОповещения при закрытии формы

Современный подход — передать в ОткрытьФорму описание оповещения, которое выполнится после закрытия формы подбора. Форма подбора при этом возвращает результат через Закрыть(Результат). Способ удобнее, когда нужен один итоговый результат, а не поток выборов.

&НаКлиенте

Процедура ПодобратьТовары(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеПодбораТоваров", ЭтотОбъект);

ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", , ЭтаФорма, , , , Оповещение);

КонецПроцедуры

&НаКлиенте

Процедура ПослеПодбораТоваров(Результат, ДопПараметры) Экспорт

Если Результат <> Неопределено Тогда

ДобавитьТоварыВТаблицу(Результат);

КонецЕсли;

КонецПроцедуры

Сравнение вариантов

ОповеститьОбИзменении

Записан или изменён объект; динамические списки обновятся сами. Не передаёт произвольные данные.

Оповестить

Произвольное событие с параметрами для всех открытых форм. Получатель должен сам отфильтровать нужное событие.

ОповеститьОВыборе

Выбор значения в открытой форме; получает только форма-владелец. Работает для множественного подбора.

ОписаниеОповещения при закрытии

Один итоговый результат после закрытия формы. Не подходит для множественного выбора без дополнительных ухищрений.

Как получить оповещение: обработчики формы

Чтобы форма «слышала» оповещения, у неё должен быть определён соответствующий обработчик. Добавляется он через панель событий формы в конфигураторе или вручную в модуле формы — с точностью до имени и параметров.

Основные обработчики: ОбработкаОповещения(ИмяСобытия, Параметр, Источник) — для Оповестить(); ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) — для ОповеститьОВыборе(); ОбработкаЗаписиНового(НовыйОбъект, Источник, СтандартнаяОбработка) — срабатывает в форме списка, когда из неё открытая форма записала новый элемент.

Типовая практика — в начале ОбработкаОповещения проверять имя события через Если ... ИначеЕсли ... и фильтровать источник, если форма должна реагировать только на конкретного отправителя. Без проверки имени форма будет реагировать на все оповещения сеанса, что приводит к лишним обновлениям и ошибкам.

Порядок действий
  1. 1
    В форме-отправителе вызовите Оповестить("ИмяСобытия", Параметр, ЭтаФорма) в клиентской процедуре
  2. 2
    В форме-получателе создайте обработчик ОбработкаОповещения с тремя параметрами
  3. 3
    Внутри обработчика проверьте ИмяСобытия на нужное значение
  4. 4
    При необходимости проверьте Источник, чтобы отсеять чужие оповещения
  5. 5
    Выполните реакцию: обновите данные, перезаполните таблицу, перечитайте объект
  6. 6
    Протестируйте: откройте обе формы, выполните действие в отправителе и убедитесь, что получатель отреагировал

Проверка результата и отладка

Простейший способ убедиться, что оповещение доходит, — временно добавить в ОбработкаОповещения вывод сообщения:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Сообщить("Оповещение: " + ИмяСобытия);

Если ИмяСобытия = "ИзмененыНастройкиОтчета" Тогда

// реакция

КонецЕсли;

КонецПроцедуры

Если сообщение не появляется, проверяйте по цепочке: вызывается ли вообще Оповестить (поставьте точку останова), открыта ли форма-получатель в момент отправки, определён ли обработчик именно в модуле формы, а не в общем модуле, совпадает ли строка имени события посимвольно — включая регистр и пробелы.

Если оповещение приходит, но реакции нет — проблема внутри условной логики обработчика: неверное имя события, лишняя проверка источника, исключение в коде реакции. Отладчик в режиме «Останавливаться по ошибке» помогает быстро локализовать такие случаи.

Контрольные точки

Как проверить результат

Сообщение из отладочного Сообщить() в ОбработкаОповещения
Норма

Появляется при каждом вызове Оповестить

Тревожный признак

Не появляется — отправитель не вызывает метод или форма закрыта

Имя события в отправителе и получателе
Норма

Строки совпадают посимвольно

Тревожный признак

Разный регистр, пробелы или опечатки — условие не срабатывает

Обновление динамического списка после ОповеститьОбИзменении
Норма

Список перечитывается автоматически

Тревожный признак

Список статичен — у списка снят флаг основной таблицы или передана не та ссылка

Типичные ошибки и ограничения

Самая частая ошибка — попытка вызвать Оповестить в серверной процедуре. Метод доступен только на клиенте; правильный паттерн — вернуть данные с сервера и отправить оповещение в клиентском продолжении.

Вторая группа ошибок связана с ожиданиями от механизма: оповещение не дойдёт до закрытой формы, не переживёт перезапуск сеанса и не доставится другому пользователю. Если нужно уведомить другого пользователя, используются обсуждения системы взаимодействия или периодический опрос данных, а не Оповестить.

Третья группа — избыточные рассылки. Вызов ОповеститьОбИзменении в цикле по тысяче ссылок заставит все открытые списки обновляться тысячу раз. В таких случаях лучше оповестить один раз после завершения обработки, передав, например, тип изменённых объектов.

Типичные ошибки
01
Вызов Оповестить в серверном контексте — метод недоступен, код падает с ошибкой
02
Опечатка в имени события у отправителя или получателя — обработчик молча не срабатывает
03
Отсутствие проверки ИмяСобытия — форма реагирует на все оповещения сеанса, лишние обновления и ошибки
04
Вызов ОповеститьОбИзменении в цикле по большому массиву — открытые списки многократно перечитываются, интерфейс подтормаживает
05
Ожидание, что оповещение дойдёт до другого пользователя или закрытой формы — механизм работает только внутри текущего сеанса

FAQ

Можно ли оповестить конкретную форму, а не все открытые?

Напрямую адресной доставки у Оповестить() нет — сообщение получают все формы с обработчиком. Адресность эмулируется через источник: передавайте в третьем параметре уникальный идентификатор формы-получателя, а в обработчике сравнивайте его со своим УникальныйИдентификатор. Для пары «открывающая — открываемая форма» лучше подходят ОповеститьОВыборе или ОписаниеОповещения при закрытии.

Почему динамический список не обновляется после ОповеститьОбИзменении?

Проверьте, что у динамического списка задана основная таблица, соответствующая типу переданной ссылки, и что список не настроен на произвольный запрос без автообновления. Также убедитесь, что передаётся именно ссылка на объект, а не, например, строка с представлением.

Чем ОповеститьОбИзменении отличается от Оповестить?

ОповеститьОбИзменении — специализированный сигнал «объект изменился», на который автоматически реагируют динамические списки и стандартные механизмы платформы. Оповестить — универсальная рассылка произвольного события, на которую платформа сама не реагирует: обработку полностью определяет разработчик.

Можно ли отправить оповещение из фонового задания?

Нет, в фоновом задании нет клиентского контекста, и методы оповещения там недоступны. Паттерн такой: фоновое задание возвращает результат (например, через ДлительныеОперации), клиентская процедура получает его в оповещении о завершении и уже там вызывает Оповестить или ОповеститьОбИзменении.

Работает ли ОбработкаОповещения в обычных формах?

Обычные формы используют другой механизм: обработчик ОбработкаОповещения там тоже существует, но вызывается через Оповестить() в контексте обычного приложения. В управляемом приложении обычные формы практически не применяются, поэтому для новых разработок ориентируйтесь на управляемые формы и описанные выше методы.

Как оповестить форму списка о записи нового элемента?

Если форма элемента открыта из формы списка, при записи нового объекта в форме списка автоматически срабатывает обработчик ОбработкаЗаписиНового. Дополнительно можно вызвать ОповеститьОбИзменении(Ссылка) — список обновится и позиционируется на новом элементе, если это предусмотрено настройками.

Итог

Что важно запомнить

Для уведомления об изменении объекта используйте ОповеститьОбИзменении — списки обновятся автоматически. Для произвольных событий — Оповестить с обработчиком ОбработкаОповещения у получателя, всегда проверяя имя события. Для выбора из подбора — ОповеститьОВыборе или ОписаниеОповещения при закрытии. Все оповещения работают только внутри текущего сеанса и только на клиенте.