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