В практике разработки на платформе 1С:Предприятие часто возникает задача ограничить выбор пользователя небольшим набором значений. При этом открывать стандартную форму выбора (справочника или документа) кажется избыточным, особенно если вариантов всего 3-4. Подобные задачи часто возникают, когда вы реализуете приемы построения эффективных интерфейсов, стремясь сделать работу пользователя более плавной и быстрой.
В этой статье мы подробно разберем, почему простой код в событии НачалоВыбора может не работать, почему список может появляться только со "второго клика", и рассмотрим правильные архитектурные решения этой задачи.
Рассмотрим типичную ситуацию, с которой столкнулся автор темы. Есть поле на управляемой форме. Если вы используете механизмы, позволяющие выполнять добавление реквизитов и элементов формы на управляемые формы динамически, важно понимать, как правильно связать их с программной логикой выбора. Мы хотим сформировать список значений в момент нажатия на кнопку выбора и показать его пользователю.
Первая интуитивная попытка реализации часто выглядит так:
&НаКлиенте
Процедура ЭлементНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
// Отключаем стандартную логику платформы (открытие формы выбора)
СтандартнаяОбработка = Ложь;
// Пытаемся заполнить данные выбора
ДанныеВыбора = Новый СписокЗначений;
ДанныеВыбора.Добавить("Вариант 1");
ДанныеВыбора.Добавить("Вариант 2");
КонецПроцедуры
Результат: При нажатии на кнопку ничего не происходит. Почему?
Когда мы устанавливаем СтандартнаяОбработка = Ложь, мы говорим платформе: "Не делай ничего, я сам все отрисую". Заполнив переменную ДанныеВыбора, мы просто создали список в памяти, но не дали команду на его отображение. Переменная ДанныеВыбора используется платформой для настройки стандартной формы выбора, но так как мы отменили ее открытие, данные просто игнорируются.
Если список значений зависит от контекста (например, от значений других полей) и формируется динамически прямо в момент клика, самым правильным способом будет использование асинхронного метода ПоказатьВыборИзСписка. Это позволяет "на лету" показать меню, не изменяя свойства самого элемента формы. Это решение гораздо изящнее, когда вам нужно ограничить выбор всего парой фиксированных значений.
Давайте напишем правильный код для этого сценария:
&НаКлиенте
Процедура ТоварНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
// 1. Отменяем стандартное открытие формы
СтандартнаяОбработка = Ложь;
// 2. Формируем список значений (можно получить с сервера)
СписокДляВыбора = Новый СписокЗначений;
// Пример получения данных (в реальности может быть вызов сервера)
СписокДляВыбора.Добавить(1, "Срочная доставка");
СписокДляВыбора.Добавить(2, "Самовывоз");
// 3. Создаем описание оповещения для обработки результата выбора
Оповещение = Новый ОписаниеОповещения("ОбработкаВыбораИзСписка", ЭтотОбъект, Элемент);
// 4. Показываем список под элементом
ПоказатьВыборИзСписка(Оповещение, СписокДляВыбора, Элемент);
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаВыбораИзСписка(ВыбранныйЭлемент, Параметры) Экспорт
// Элемент - это поле формы, которое мы передали в контексте
ПолеФормы = Параметры;
Если ВыбранныйЭлемент <> Неопределено Тогда
// Записываем выбранное значение в реквизит, связанный с полем
ЭтаФорма[ПолеФормы.Имя] = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецПроцедуры
Преимущества метода:
СписокВыбора самого элемента формы, что важно, если логика сложная.В теме обсуждалась попытка загрузить данные напрямую в Элемент.СписокВыбора внутри события НачалоВыбора:
// ОШИБОЧНЫЙ ПОДХОД, вызывающий проблему "двух кликов"
Элемент.СписокВыбора.ЗагрузитьЗначения(МассивЗначений);
Проблема "второго клика": Если вы меняете состав СписокВыбора прямо в момент нажатия на кнопку, платформа может уже успеть инициализировать выпадающее окно со старым состоянием. Для автоматизации подобных манипуляций разработчики часто используют программное изменение форм, которое позволяет стандартизировать управление свойствами элементов.
Как сделать правильно через СписокВыбора?
Если мы хотим использовать именно встроенный механизм выпадающего списка (свойство поля РежимВыбораИзСписка), то список нужно заполнять заранее, а не в момент клика.
Если набор значений не меняется (например, типы документов), заполняем его при создании формы на сервере.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элементы.МоеПоле.РежимВыбораИзСписка = Истина;
Элементы.МоеПоле.СписокВыбора.Добавить("Значение1");
Элементы.МоеПоле.СписокВыбора.Добавить("Значение2");
КонецПроцедуры
Если список зависит от другого поля (например, при выборе "Страны" меняется список "Городов"), мы должны обновлять список городов в момент изменения страны, а не в момент попытки выбрать город.
&НаКлиенте
Процедура СтранаПриИзменении(Элемент)
// Очищаем и заполняем список городов
Элементы.Город.СписокВыбора.Очистить();
// Получаем новые данные (условно)
НовыйСписок = ПолучитьГородаПоСтране(Объект.Страна);
// Загружаем в элемент
Для Каждого Стр Из НовыйСписок Цикл
Элементы.Город.СписокВыбора.Добавить(Стр.Значение, Стр.Представление);
КонецЦикла;
КонецПроцедуры
В этом случае платформе не требуется дополнительного кода в НачалоВыбора, она сама покажет заполненный список.
Автор темы в итоге пришла к использованию свойства ДоступныеЗначения. Однако, чтобы поле работало как строгий выпадающий список (Combo Box), необходимо правильно настроить свойства элемента формы. Если вы хотите быстро протестировать различные настройки элементов интерфейса без изменения конфигурации, вам может пригодиться редактор форм в режиме предприятия.
Основные настройки для этого подхода:
РежимВыбораИзСписка = Истина. Это меняет иконку кнопки на "стрелку вниз".РедактированиеТекста = Ложь (опционально).В теме справедливо заметили проблему: история выбора может подсказать пользователю "старое" значение, которое уже неактуально. При работе со сложными интерфейсами, например, реализуя флажок в динамическом списке, разработчики часто сталкиваются с необходимостью тонкой настройки поведения элементов ввода.
Для корректной работы динамических ограниченных списков рекомендуется устанавливать свойство поля:
ИсторияВыбораПриВводе = НеИспользовать.
Давайте резюмируем. Чтобы вывести список из 4-х значений вместо открытия формы выбора, у нас есть два основных пути:
Путь 1 (Интерактивный): Если список сложный и вычисляется в момент клика — используйте СтандартнаяОбработка = Ложь и метод ПоказатьВыборИзСписка.
Путь 2 (Свойство элемента): Если вы хотите классический выпадающий список ("ComBobox"), установите у элемента свойство РежимВыбораИзСписка = Истина и заполняйте коллекцию СписокВыбора до того, как пользователь нажмет на кнопку (при создании формы или при изменении влияющих реквизитов).