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