При работе с иерархическими данными в 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью реализовать кнопку «Развернуть всё». Стандартное поведение платформы не всегда позволяет сделать это одной командой, особенно если речь идет о динамических списках. В этой статье мы подробно разберем, как эффективно управлять раскрытием узлов дерева на управляемой форме, рассмотрим особенности работы с динамическими данными и проанализируем возможные проблемы производительности.
Самый правильный и «чистый» с точки зрения архитектуры платформы способ — это использование метода Развернуть() элемента формы. Рассмотрим ситуацию, когда у нас есть таблица, отображающая ДеревоЗначений или ДинамическийСписок с иерархией. Чтобы развернуть конкретный узел и все его дочерние элементы, необходимо вызвать метод с параметром Истина во втором аргументе.
Проанализируем пример кода для развертывания всей иерархии. Важно понимать, что метод Развернуть() работает с идентификаторами строк, а не с самими данными. Чтобы развернуть все дерево целиком, нам необходимо обойти все строки верхнего уровня и применить к ним этот метод рекурсивно.
&НаКлиенте
Процедура РазвернутьВсеДерево(Команда)
// Получаем все элементы верхнего уровня дерева
СтрДерева = Элементы.Список.ДанныеСтроки(Элементы.Список.ТекущаяСтрока);
// Если нужно развернуть вообще всё, придется обойти коллекцию
// Для ДереваЗначений это делается через получение корня
// Для ДинамическогоСписка — сложнее из-за порционной загрузки
ИдентификаторыОснования = Элементы.Список.ДанныеСтроки(Неопределено); // Пример получения корня
// Основной метод для развертывания текущей ветки и всех вложенных:
Элементы.Список.Развернуть(Элементы.Список.ТекущаяСтрока, Истина);
КонецПроцедуры
Обратите внимание на второй параметр Истина. Он указывает платформе, что развертывание должно быть полным, включая все уровни подчинения. Если передать Ложь, развернется только один уровень.
Рассмотрим интересную особенность динамических списков. Если программно изменить свойство Отображение таблицы, а затем вернуть его обратно, платформа может перерисовать дерево с учетом настроек начального отображения. Выясним, как это можно использовать для реализации кнопки развертывания/свертывания всей иерархии.
Этот способ часто называют «хаком», но он оказывается весьма эффективным, когда обычные методы не срабатывают при повторном нажатии. Разберем по шагам алгоритм, предложенный участниками сообщества:
Отображение таблицы из состояния Дерево в Список. Это заставляет платформу сбросить кэш развернутых узлов.НачальноеОтображениеДерева в значение РаскрыватьВсеУровни.Отображение обратно в состояние Дерево.Пример реализации такой процедуры:
&НаКлиенте
Процедура КомандаРазвернутьСвернуть(Команда)
Если Элементы.Список.Отображение = ОтображениеТаблицы.Дерево Тогда
// Переключаем в режим списка, чтобы "сбросить" дерево
Элементы.Список.Отображение = ОтображениеТаблицы.Список;
Команда.Заголовок = "Развернуть дерево";
Иначе
// Устанавливаем режим раскрытия всех уровней
Элементы.Список.НачальноеОтображениеДерева = НачальноеОтображениеДерева.РаскрыватьВсеУровни;
// Возвращаем режим дерева
Элементы.Список.Отображение = ОтображениеТаблицы.Дерево;
Команда.Заголовок = "Свернуть в список";
КонецЕсли;
КонецПроцедуры
Важный нюанс: при таком подходе визуально структура может измениться (исчезнут иерархические связи при переключении в список), поэтому используйте этот метод с осторожностью, понимая ожидания пользователя.
Проанализируем ситуацию с точки зрения производительности. В 1С ДинамическийСписок работает по принципу «ленивой загрузки». Это означает, что данные с сервера подтягиваются только тогда, когда пользователь раскрывает ветку или прокручивает список.
Если мы пытаемся программно заставить ДинамическийСписок развернуть тысячи узлов одновременно:
Рекомендация: Если в вашем справочнике более 500-1000 групп, лучше отказаться от идеи полного развертывания. Вместо этого используйте поиск или разворачивайте дерево только до определенного уровня (например, до второго или третьего).
Рассмотрим способ, который упоминался как «попытка имитации нажатия клавиш». В среде Windows можно отправить команду нажатия клавиш Ctrl + Shift + Num+ (это стандартное сочетание в 1С для раскрытия дерева). Однако в коде часто допускают ошибки. Если вы решили использовать этот «костыль», то синтаксис должен быть следующим:
ОбъектShell = Новый COMОбъект("Wscript.Shell");
// Символ "+" нужно заключать в фигурные скобки, так как сам по себе он означает Shift
ОбъектShell.SendKeys("^+{ADD}"); // ADD — это код плюса на цифровой клавиатуре
Почему мы не рекомендуем этот метод? Во-первых, он работает только в операционной системе Windows. Во-вторых, фокус ввода должен находиться строго на элементе формы «Список», иначе команда уйдет «в никуда». В-третьих, использование COM-объектов постепенно ограничивается в современных системах безопасности.
Подводя итог, можно выделить оптимальную стратегию для программиста 1С:
Развернуть(Идентификатор, Истина).НачальноеОтображениеДерева при открытии формы, либо метод с переключением режима отображения, если развертывание нужно выполнять «на лету».