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