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