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