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