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