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

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

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

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

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

В управляемом приложении 1С 8.3 экземпляр объекта обработки не живет постоянно. Рассмотрим этот процесс по шагам:

  1. Когда открывается любая форма, на сервере создается структура ДанныеФормыСтруктура, которая в интерфейсе называется Объект. Это лишь проекция данных, а не сам реальный объект обработки.
  2. В момент вызова серверного метода (например, ПриСозданииНаСервере) система на мгновение создает реальный экземпляр обработки в памяти сервера, «накатывает» на него данные из структуры формы, выполняет код и тут же уничтожает экземпляр. Измененные данные возвращаются обратно в структуру формы.
  3. Важный вывод: Каждая новая открытая форма создает свою собственную, независимую структуру Объект. Даже если обе формы принадлежат одной обработке, они никак не связаны друг с другом автоматически. Изменения в Объект формы №1 никогда не попадут в Объект формы №2 без вашего участия.

Способ 1: Использование параметров формы и КопироватьДанныеФормы

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

В вызывающей (основной) форме мы подготавливаем структуру параметров и открываем вторую форму:


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

Теперь разберем, как принять эти данные в открываемой форме. Для этого используется процедура ПриСозданииНаСервере и метод КопироватьДанныеФормы. Этот метод позволяет быстро перенести значения всех совпадающих реквизитов из одного источника в другой.


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

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

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

Иногда бывает удобно обратиться к данным формы, которая инициировала открытие. В 1С существует свойство ВладелецФормы. Если при открытии второй формы вы указали ЭтаФорма в качестве владельца, то во второй форме можно получить доступ к ее данным.

Посмотрим, как это выглядит в коде открытой формы:


&НаСервере
Процедура ЗаполнитьИзВладельца()
    // Проверяем, что владелец - это форма и у нее есть нужный нам реквизит
    Если ТипЗнч(ЭтаФорма.ВладелецФормы) = Тип("УправляемаяФорма") Тогда
        // Прямое обращение к объекту владельца
        // Внимание: на сервере это сработает только если форма владельца еще "жива"
        КопироватьДанныеФормы(ЭтаФорма.ВладелецФормы.Объект, Объект);
    КонецЕсли;
КонецПроцедуры

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

Способ 3: Перенос логики в Модуль объекта

Часто разработчики пытаются сохранить данные в реквизитах обработки, чтобы избежать дублирования кода функций. Но правильный путь в 1С — это вынос общей логики в Модуль объекта с ключевым словом Экспорт.

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


// В модуле объекта обработки
Функция ПолучитьАдресЗвуковогоФайла(ИмяФайла) Экспорт
    // Здесь ваша логика получения адреса
    Возврат ПолучитьАдресФайлаВХранилище(ИмяФайла); 
КонецФункции

Теперь в любой форме вы можете вызвать эту логику через преобразование реквизита формы в значение объекта:


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

Именно связка РеквизитФормыВЗначение и ЗначениеВРеквизитФормы является «мостиком» между миром долгоживущих данных формы и кратковременным миром серверных объектов.

Способ 4: Временное хранилище для сложных данных

Если ваша обработка оперирует большими объемами данных (таблицы значений, двоичные данные), которые неудобно передавать через параметры, проанализируем механизм Временного хранилища.

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

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

Резюме

Выясним главные правила работы с формами одного объекта:

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

← На главную