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