При разработке интерфейсов в 1С часто возникает задача: предоставить пользователю возможность выбрать один конкретный вариант из динамически сформированного набора данных (например, полученного из запроса к регистру сведений или табличной части). Начинающие разработчики нередко создают реквизит формы с типом СписокЗначений и выводят его на форму. В результате вместо компактного выпадающего меню на форме появляется таблица со списком, где элементы можно только редактировать, отмечать флажками или удалять, но не выбирать в качестве итогового значения поля.
Разберем причины такого поведения платформы и подробно рассмотрим два основных и правильных способа решения этой задачи на управляемых формах.
Проанализируем механику работы платформы 1С. Объект СписокЗначений предназначен для хранения коллекции элементов. Когда мы перетаскиваем реквизит формы типа СписокЗначений на элемент интерфейса, платформа автоматически создает элемент управления Таблица формы. Этот элемент служит для управления всем списком целиком: добавления новых строк, удаления существующих, изменения представлений и установки пометок.
Если наша цель — сохранить одно выбранное значение, то реквизит формы должен иметь тип самого этого значения (например, Число, Строка, ссылка на справочник или Произвольный), а список возможных вариантов должен подключаться к элементу формы через свойство СписокВыбора либо вызываться модально/асинхронно через методы платформы.
Рассмотрим самый удобный и стандартный вариант создания выпадающего списка. Он позволяет пользователю выбирать значение прямо в поле ввода без открытия лишних диалоговых окон.
Выполним по шагам следующую настройку:
ВыбранныйВариант с типом Строка или Число).РежимВыбораИзСписка = Истина).Истина, а свойство КнопкаВыбора отключим (Ложь), чтобы исключить вызов стандартного окна выбора ссылок.Посмотрим на пример программного заполнения списка выбора элемента формы:
&НаСервере
Процедура ЗаполнитьСписокВыбораНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СведенияОДоступах.Пароль,
| СведенияОДоступах.ВидДоступа,
| СведенияОДоступах.АдресДоступа,
| СведенияОДоступах.Протокол,
| СведенияОДоступах.УчетнаяЗапись
|ИЗ
| РегистрСведений.СведенияОДоступах.СрезПоследних(, Оборудование = &Оборудование) КАК СведенияОДоступах
|УПОРЯДОЧИТЬ ПО
| СведенияОДоступах.Протокол";
Запрос.УстановитьПараметр("Оборудование", Объект.Ссылка);
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// Получаем список выбора элемента формы
Список = Элементы.ВыбранныйВариант.СписокВыбора;
Список.Очистить();
Индекс = 0;
Для Каждого Стр Из ТаблицаДанных Цикл
Представление = СтрШаблон("[%1] %2 / %3", Индекс, Стр.ВидДоступа, Стр.АдресДоступа);
// В качестве значения сохраняем индекс, ключ или конкретное поле
Список.Добавить(Индекс, Представление);
Индекс = Индекс + 1;
КонецЦикла;
КонецПроцедуры
Если необходимо динамически обновлять данные только в момент клика пользователя по выпадающему списку, можно использовать событие элемента формы НачалоВыбораИзСписка. Это позволяет не тратить ресурсы сервера при инициализации формы, если пользователь так и не откроет список.
Бывают ситуации, когда выбор нужно запросить разово по нажатию отдельной кнопки команды. Для этого используется программный объект СписокЗначений и методы выбора платформы.
В современных версиях платформы 1С при запрете модальности устаревшие синхронные методы (ВыбратьЭлемент(), ВыбратьИзСписка()) вызывают исключение. Разберем правильный асинхронный вызов.
Вариант А: Использование конструкции «Ждать» в асинхронной процедуре:
&НаКлиенте
Асинх Процедура ВыбратьВариантКоманда(Команда)
// Формируем список значений (например, переданный с сервера)
СписокВариантов = Новый СписокЗначений;
СписокВариантов.Добавить("Вариант1", "Основная таблица доступа");
СписокВариантов.Добавить("Вариант2", "Резервная таблица доступа");
СписокВариантов.Добавить("Вариант3", "Архивные данные");
// Вызываем асинхронный диалог выбора
ВыбранныйЭлемент = Ждать СписокВариантов.ВыбратьЭлементАсинх("Выберите нужную таблицу:");
Если ВыбранныйЭлемент <> Неопределено Тогда
// Обрабатываем выбранное значение
ЗначениеВыбора = ВыбранныйЭлемент.Значение;
ПоказатьОповещениеПользователя("Выбор сделан", , ВыбранныйЭлемент.Представление);
// Выполняем дальнейшие действия с полученным значением
ОбработатьВыборНаСервере(ЗначениеВыбора);
КонецЕсли;
КонецПроцедуры
Вариант Б: Использование функции «ПоказатьВыборИзСписка» с описанием оповещения:
&НаКлиенте
Процедура ВыбратьИзСпискаОповещение(Команда)
СписокВариантов = Новый СписокЗначений;
ЗаполнитьСписокНаСервере(СписокВариантов);
Оповещение = Новый ОписаниеОповещения("ПослеВыбораИзСписка", ЭтотОбъект);
ПоказатьВыборИзСписка(Оповещение, СписокВариантов, Элементы.КнопкаВыбора);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораИзСписка(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
Если ВыбранныйЭлемент <> Неопределено Тогда
// Извлекаем значение из возвращенного объекта ЭлементСпискаЗначений
ТекущееЗначение = ВыбранныйЭлемент.Значение;
Сообщить("Пользователь выбрал: " + ВыбранныйЭлемент.Представление);
КонецЕсли;
КонецПроцедуры
В зависимости от объема данных и структуры интерфейса можно применить и другие решения:
ВидПоляФормы.ПолеПереключателя и заполнить его СписокВыбора. Это дает возможность выбирать вариант в один клик мышью.АвтоПодбор или ОкончаниеВводаТекста, фильтруя данные по первым введенным символам.Таким образом, для выбора одного значения следует использовать реквизит базового типа с настройкой СписокВыбора элемента формы либо вызывать асинхронные методы ВыбратьЭлементАсинх() / ПоказатьВыборИзСписка().