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