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