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