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