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