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