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