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