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