Как передать реквизиты между несколькими формами обработки и прикладным объектом в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки сложных обработок в среде 1С:Предприятие 8.3 на управляемых формах часто возникает ситуация, когда в обработке существует основная форма и несколько вспомогательных. Типичная проблема заключается в том, что изменения реквизитов (например, какого-либо настроечного флага), внесенные в одной форме, не «видны» в другой или в модуле объекта этой же обработки. Разберем подробно, почему это происходит и как правильно организовать передачу данных.

Анализируем причину проблемы: жизненный цикл объекта на сервере

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

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

Проанализируем ситуацию: когда вы открываете вспомогательную форму из основной, платформа создает новый, независимый контекст. Реквизит Объект во вспомогательной форме никак не связан с реквизитом Объект в основной форме. Более того, при вызове метода РеквизитФормыВЗначение каждый раз создается новый экземпляр объекта обработки, который заполняется данными именно из той формы, откуда был вызван метод.

Способ 1. Передача данных через параметры формы (рекомендуемый)

Для того чтобы вспомогательная форма «знала» о состоянии настроек основной формы, мы должны явно передать эти значения при открытии. Рассмотрим, как это реализовать по шагам.

Во-первых, в основной форме при открытии вспомогательной формы подготовим структуру параметров:


// Код в модуле основной формы
&НаКлиенте
Процедура ОткрытьДополнительнуюФорму()
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("Флаг", Объект.Флаг); // Передаем текущее значение флага
    
    ОткрытьФорму("Обработка.МояОбработка.Форма.ВспомогательнаяФорма", ПараметрыОткрытия);
КонецПроцедуры

Во-вторых, во вспомогательной форме в обработчике ПриСозданииНаСервере нам необходимо принять этот параметр и записать его в локальный реквизит Объект. Выясним причину, по которой это важно: только если данные находятся в Объект, они попадут в прикладной объект при конвертации.


// Код в модуле вспомогательной формы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("Флаг") Тогда
        Объект.Флаг = Параметры.Флаг;
    КонецЕсли;
КонецПроцедуры

Теперь, если во вспомогательной форме потребуется вызвать процедуру из модуля объекта, которая опирается на этот флаг, мы будем использовать стандартный механизм:


&НаСервере
Процедура ВыполнитьДействиеНаСервере()
    // Конвертируем данные формы в объект. Флаг уже будет заполнен из Объект.Флаг
    ОбъектОбработка = РеквизитФормыВЗначение("Объект");
    
    // Вызываем экспортную процедуру модуля объекта
    ОбъектОбработка.ВыполнитьЛогику(); 
КонецПроцедуры

Способ 2. Использование механизма «Владелец формы»

Если вспомогательная форма открывается строго из основной, мы можем использовать свойство ВладелецФормы. Посмотрим на пример реализации, где вспомогательная форма обращается к данным основной формы напрямую на клиенте:

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

Способ 3. Передача через Временное хранилище

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

  1. В основной форме помещаем данные в хранилище: Адрес = ПоместитьВоВременноеХранилище(Данные, ЭтаФорма.УникальныйИдентификатор);.
  2. Передаем Адрес как параметр во вспомогательную форму.
  3. Во вспомогательной форме извлекаем данные: Данные = ПолучитьИзВременногоХранилища(Параметры.Адрес);.

Важные нюансы работы с РеквизитФормыВЗначение

Выясним важную деталь, упомянутую в обсуждении на форуме: метод РеквизитФормыВЗначение создает объект «здесь и сейчас». Если вы изменили значение в Объект.Флаг, а затем снова вызвали РеквизитФормыВЗначение, будет создан новый объект с обновленным флагом. Но если вы сначала создали объект, а потом изменили Объект.Флаг в коде формы, уже созданный ранее экземпляр объекта не обновится автоматически. Это разные области памяти.

Правило: Всегда сначала устанавливайте значения в реквизитах формы (Объект.ИмяРеквизита = Значение), и только после этого выполняйте преобразование РеквизитФормыВЗначение("Объект"), если вам нужно вызвать процедуры модуля объекта.

Резюме для практического применения

Подводя итог, для корректной работы с несколькими формами обработки придерживайтесь следующих принципов:

Соблюдение этой архитектурной логики позволит вам избежать «мистического» исчезновения данных при переходах между формами и обеспечит стабильную работу бизнес-логики в модуле объекта обработки.

← На главную