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