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