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