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