Как правильно программно заполнять список выбора в 1С и избежать дублирования элементов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки интерфейсов на платформе 1С:Предприятие 8 часто возникает задача динамического изменения доступных вариантов выбора в зависимости от состояния других реквизитов формы. Типичный пример — выбор окончания фамилии или формы обращения, который напрямую зависит от указанного пола сотрудника или контрагента. Однако начинающие разработчики часто сталкиваются с тем, что при повторном выборе значения в основном поле список доступных вариантов начинает бесконечно расти, дублируя одни и те же строки. В этой статье мы подробно разберем, как правильно управлять объектом СписокВыбора, чтобы интерфейс работал корректно и профессионально.

Анализ проблемы: почему дублируются значения?

Рассмотрим ситуацию, когда в обработчике события ПриИзменении для поля Пол мы прописываем логику добавления элементов в список выбора другого поля. Проблема заключается в том, что метод Добавить() просто вставляет новую запись в существующую коллекцию. Если пользователь трижды сменит значение в поле Пол, в списке выбора окончаний фамилий соберется три одинаковых набора данных. Наша задача — обеспечить актуальность списка, соответствующую текущему состоянию объекта, исключая избыточность.

Решение 1: Использование метода Очистить()

Самый простой и эффективный способ избежать дублирования — это полная очистка коллекции перед её заполнением. Проанализируем программный код, который решает эту задачу. Мы будем использовать обработчик события на клиенте, так как работа с элементами формы происходит в контексте клиентского сеанса.

Разберем по шагам реализацию в процедуре ПолПриИзменении:


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

В данном примере мы сначала вызываем метод Очистить(), который удаляет все предыдущие варианты. Только после этого, в зависимости от условия, мы заново наполняем СписокВыбора нужными строками. Это гарантирует, что пользователь всегда увидит только актуальные варианты.

Решение 2: Оптимизация через метод ЗагрузитьЗначения()

Если вариантов выбора много, многократный вызов метода Добавить() может сделать код громоздким. Рассмотрим более профессиональный подход с использованием массива и метода ЗагрузитьЗначения(). Этот метод за один проход полностью заменяет содержимое списка выбора данными из переданного массива.


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

Решение 3: Динамическое формирование в событии НачалоВыбора

Иногда нецелесообразно пересчитывать список при каждом изменении пола, особенно если на форме много зависимых полей. Мы можем формировать список непосредственно в тот момент, когда пользователь нажимает на кнопку выбора в поле ОкончанияФамилий. Для этого используется событие НачалоВыбора.

Проанализируем этот подход:

  1. Установим у элемента формы свойство КнопкаСпискаВыбора в значение Да.
  2. В обработчике события установим СтандартнаяОбработка = Ложь, чтобы система не пыталась открыть стандартное окно выбора.

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

Важные настройки интерфейса (UX/UI)

Для того чтобы программно заполненный список работал так, как ожидает пользователь, необходимо обратить внимание на несколько свойств элемента формы в конфигураторе:

Архитектурный совет: вынос логики в общие модули

Если логика определения окончаний по полу будет использоваться в разных частях системы (например, в справочнике сотрудников и в документе приема на работу), не стоит дублировать программный код в каждой форме. Проанализируем, как вынести это в общий модуль:

  1. Создадим общий модуль РаботаСИнтерфейсомКлиентСервер.
  2. Напишем функцию, возвращающую массив нужных строк.

// В общем модуле
Функция ПолучитьСписокОкончаний(Пол) Экспорт
    Результат = Новый Массив;
    Если Пол = ПредопределенноеЗначение("Перечисление.Пол.Мужской") Тогда
        Результат.Добавить("ов");
        // ...
    КонецЕсли;
    Возврат Результат;
КонецФункции

// В форме документа
&НаКлиенте
Процедура ПолПриИзменении(Элемент)
    МассивДанных = РаботаСИнтерфейсомКлиентСервер.ПолучитьСписокОкончаний(Объект.Пол);
    Элементы.ОкончанияФамилий.СписокВыбора.ЗагрузитьЗначения(МассивДанных);
КонецПроцедуры

Такой подход делает ваш код чистым, модульным и легким в поддержке. Мы рассмотрели все основные способы управления списками выбора, от простого метода Очистить() до выноса бизнес-логики в общие модули платформы.

← На главную