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