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