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