Как развернуть дерево на управляемой форме после перечитывания или записи данных?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В управляемых формах 1С при работе с таблицами, отображаемыми в виде дерева значений, разработчики часто сталкиваются с ситуацией: свойство элемента формы Начальное отображение дерева установлено в значение Раскрывать все уровни, однако при выполнении стандартной команды Перечитать, после записи объекта или перед формированием печатных форм дерево автоматически сворачивается к верхнему уровню. Разберем причины такого поведения платформы и подробно рассмотрим варианты решения этой задачи.

Почему дерево сворачивается и где кроется ограничение платформы

Свойство Начальное отображение дерева срабатывает исключительно при первичной инициализации формы и открытии окна. Когда в процессе работы вызывается процедура перечитывания данных, перезаполняются коллекции формы через ЗначениеВРеквизитФормы() или выполняется чтение объекта из базы, платформа пересоздает структуру строк, а визуальное состояние узлов сбрасывается в исходное свернутое состояние.

Главная сложность заключается в разделении клиентского и серверного контекстов:

  1. Серверные обработчики ПриЧтенииНаСервере и ПередЧтениемНаСервере выполняются на стороне сервера, где недоступны методы управления визуальным состоянием элементов формы.
  2. Метод управления узлами Элементы.ИмяТаблицы.Развернуть() может выполняться только в клиентском контексте (&НаКлиенте).
  3. В типовом событии чтения объекта на уровне платформы отсутствует парное клиентское событие (нет встроенного события вроде ПослеЧтенияНаКлиенте).

Проанализируем практические способы обхода этого ограничения для различных пользовательских сценариев.

Способ 1. Замена стандартной команды «Перечитать» собственной командой

Если требуется контролировать разворачивание дерева именно по кнопке обновления данных, самым надежным решением является отключение стандартной кнопки командной панели и создание собственной пользовательской команды.

Разберем по шагам создание такой команды:

  1. В командной панели формы скрываем стандартную кнопку «Перечитать» (или отключаем автозаполнение командной панели).
  2. Создаем команду формы ПеречитатьДанныеИРазвернуть и выносим ее на панель.
  3. В обработчике команды на клиенте выполняем серверное перечитывание объекта и затем разворачиваем дерево.

Посмотрим на пример реализации:


&НаКлиенте
Процедура ПеречитатьДанныеИРазвернуть(Команда)
    // 1. Вызываем серверную процедуру перечитывания
    ПеречитатьДанныеНаСервере();
    
    // 2. Разворачиваем дерево на клиенте
    РазвернутьВсеДерево();
КонецПроцедуры

&НаСервере
Процедура ПеречитатьДанныеНаСервере()
    Прочитать(); // Перечитываем основной реквизит формы Объект
    // При необходимости выполняем дополнительное заполнение реквизитов формы
КонецПроцедуры

&НаКлиенте
Процедура РазвернутьВсеДерево()
    // Обходим только строки первого уровня с параметром СПодчиненными = Истина
    Для Каждого СтрокаВерхнегоУровня Из ДеревоРеквизит.ПолучитьЭлементы() Цикл
        Идентификатор = СтрокаВерхнегоУровня.ПолучитьИдентификатор();
        Элементы.ТаблицаДерево.Развернуть(Идентификатор, Истина);
    КонецЦикла;
КонецПроцедуры

Обратите внимание: второй параметр метода Развернуть() принимает булево значение СПодчиненными. Передавая значение Истина, мы избавляемся от необходимости писать глубокий рекурсивный обход всех дочерних узлов — достаточно вызвать метод только для элементов верхнего уровня.

Способ 2. Разворачивание дерева в событии «ПослеЗаписи» на клиенте

Часто сворачивание дерева происходит при проведении, сохранении или печати документа, когда перед отправкой на печать форма автоматически инициирует запись. В этом случае переопределять стандартные кнопки не требуется — достаточно использовать стандартное клиентское событие формы ПослеЗаписи.

Рассмотрим код обработчика:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    // После успешной записи и обновления данных формы восстанавливаем развернутое состояние
    РазвернутьВсеДерево();
КонецПроцедуры

Способ 3. Использование однократного обработчика ожидания

Если обновление данных инициируется из сложных цепочек вызовов (например, через подписки, обработчики оповещений или модальные диалоги), у которых нет прямого клиентского завершающего события, можно использовать перенос выполнения на следующий такт клиентского цикла через ПодключитьОбработчикОжидания().

Посмотрим, как подключить обработчик ожидания:


&НаКлиенте
Процедура ЗапуститьОбновлениеДерева()
    // Выполняем серверные действия
    ОбновитьДанныеДереваНаСервере();
    
    // Подключаем однократный вызов разворачивания с минимальной задержкой
    ПодключитьОбработчикОжидания("РазвернутьВсеДерево", 0.1, Истина);
КонецПроцедуры

Способ 4. Сохранение и восстановление состояния узлов

В некоторых сценариях разворачивать абсолютно все узлы не требуется — пользователю важно сохранить именно ту структуру, которую он раскрыл вручную до нажатия кнопки записи или обновления.

Разберем алгоритм решения этой задачи:

  1. Перед выполнением операции на клиенте собираем идентификаторы или ключевые поля строк, для которых метод Элементы.ТаблицаДерево.Развернут(ИдентификаторСтроки) возвращает Истина.
  2. Выполняем операцию обновления данных на сервере.
  3. После обновления данных на клиенте сопоставляем строки по сохраненным ключевым полям и вызываем метод Развернуть(ИдентификаторНовойСтроки, Ложь) только для ранее открытых узлов.

Использование функций Библиотеки стандартных подсистем (БСП)

Если в конфигурации используется БСП, можно применить готовые платформенные механизмы общего клиентского модуля. Для этого достаточно передать элемент формы и строки коллекции в процедуру СтандартныеПодсистемыКлиент.РазвернутьУзлыДерева(ЭлементФормы, СтрокиДерева), что упрощает поддержку и стандартизирует код формы.

← На главную