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

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

При переходе с обычных форм на управляемые разработчики часто сталкиваются с трудностями при работе с иерархическими структурами — деревьями значений. В обычных формах для анализа строки использовались свойства вроде ЭлементыФормы.ДеревоНастроек.ТекущаяСтрока и прямой вызов метода Уровень(). В управляемых формах модель данных устроена иначе: на клиенте таблица дерева представлена объектом ДанныеФормыДерево, а её строки — ДанныеФормыЭлементДерева.

Разберем подробнее, как получить данные текущей строки, определить её родительский узел и уровень вложенности, а также как корректно организовать выбор значений из динамического списка.

Получение текущей строки и родительских данных на клиенте

Проанализируем базовый способ обращения к активной строке таблицы дерева. В управляемой форме для элемента формы «Таблица» доступны два ключевых свойства:

  1. Элементы.ИмяДерева.ТекущаяСтрока — возвращает числовой идентификатор выбранной строки.
  2. Элементы.ИмяДерева.ТекущиеДанные — возвращает саму текущую строку в виде объекта ДанныеФормыЭлементДерева, предоставляя прямой доступ ко всем колонкам строки.

Посмотрим на пример: если нам необходимо получить родителя текущей строки, у объекта ДанныеФормыЭлементДерева вызывается метод ПолучитьРодителя(). Сделать это можно как через ТекущиеДанные, так и через поиск по идентификатору.


// Вариант 1: Прямое обращение через ТекущиеДанные
ТекущаяСтрока = Элементы.ДеревоНастроек.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
    РодительСтроки = ТекущаяСтрока.ПолучитьРодителя();
    Если РодительСтроки <> Неопределено Тогда
        ИмяРодителя = РодительСтроки.Наименование;
    КонецЕсли;
КонецЕсли;

// Вариант 2: Поиск строки по идентификатору в реквизите формы
ИдентСтроки = Элементы.ДеревоНастроек.ТекущаяСтрока;
Если ИдентСтроки <> Неопределено Тогда
    СтрокаДерева = ДеревоНастроек.НайтиПоИдентификатору(ИдентСтроки);
    РодительСтроки = СтрокаДерева.ПолучитьРодителя();
КонецЕсли;

Определение уровня строки дерева

Выясним причину частой ошибки: на сервере у объекта СтрокаДереваЗначений существует метод Уровень(), однако на клиенте у объекта ДанныеФормыЭлементДерева такого метода нет. Попытка вызвать ТекущиеДанные.Уровень() вызовет исключение платформы.

Существует два пути решения этой задачи:

  1. Хранить уровень в отдельной колонке дерева: при заполнении или интерактивном добавлении строки явно рассчитывать и заполнять реквизит Уровень.
  2. Динамический подсчет через обход родителей: подниматься вверх по иерархии до корневого узла. Этот способ надежнее, так как исключает рассинхронизацию данных.

Рассмотрим реализацию функции динамического вычисления уровня на клиенте:


&НаКлиенте
Функция ПолучитьУровеньСтроки(СтрокаДерева)
    Уровень = 0;
    РодительУзла = СтрокаДерева.ПолучитьРодителя();
    
    Пока РодительУзла <> Неопределено Цикл
        Уровень = Уровень + 1;
        РодительУзла = РодительУзла.ПолучитьРодителя();
    КонецЦикла;
    
    Возврат Уровень;
КонецФункции

Особенности изменения списка выбора в управляемых формах

В обычных формах разработчики часто использовали событие НачалоВыбораИзСписка. Однако в управляемых формах (начиная с платформы 8.3.3 без режима совместимости) это событие и свойство КнопкаСпискаВыбора устарели и не обрабатываются платформой.

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

Разберем два правильных способа реализации выбора в зависимости от задачи.

Способ 1: Использование метода «ПоказатьВыборИзСписка» (рекомендуемый)

Этот подход универсален, работает асинхронно и не меняет свойства колонки для других строк дерева. Разберем реализацию по шагам:

  1. В свойствах поля ввода колонки устанавливаем свойство КнопкаВыбора = Да.
  2. Создаем обработчик события НачалоВыбора для поля ввода.
  3. Устанавливаем СтандартнаяОбработка = Ложь, формируем список доступных значений и открываем контекстный список выбора.

&НаКлиенте
Процедура ДеревоНастроекВидОперацииНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    ТекущаяСтрока = Элементы.ДеревоНастроек.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    УровеньСтроки = ПолучитьУровеньСтроки(ТекущаяСтрока);
    Список = Новый СписокЗначений;
    
    Если УровеньСтроки = 0 Тогда
        Список.Добавить("CashFlow");
    ИначеЕсли УровеньСтроки = 1 Тогда
        Список.Добавить("ОборотДТ");
        Список.Добавить("ОборотКТ");
    ИначеЕсли УровеньСтроки = 2 Тогда
        Родитель = ТекущаяСтрока.ПолучитьРодителя();
        ИмяРодителя = ?(Родитель <> Неопределено, Родитель.Наименование, "");
        
        Если ИмяРодителя = "Отбор" Или ИмяРодителя = "Вывод" Тогда
            Список.Добавить("ОборотДТ");
            Список.Добавить("ОборотКТ");
        ИначеЕсли ИмяРодителя = "Распределение" Тогда
            Список.Добавить("База");
            Список.Добавить("Коэффициент");
        КонецЕсли;
    КонецЕсли;
    
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораВидаОперации", ЭтотОбъект);
    ПоказатьВыборИзСписка(Оповещение, Список, Элемент);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораВидаОперации(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        Элементы.ДеревоНастроек.ТекущиеДанные.ВидОперации = ВыбранныйЭлемент.Значение;
    КонецЕсли;
КонецПроцедуры

Способ 2: Обновление списка выбора в событии «ПриАктивизацииСтроки»

Если колонка хранит простые строковые данные (где представление полностью эквивалентно значению), допускается перезаполнять свойство поля СписокВыбора непосредственно при переходе по строкам таблицы дерева.


&НаКлиенте
Процедура ДеревоНастроекПриАктивизацииСтроки(Элемент)
    ТекущаяСтрока = Элемент.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ПолеВыбора = Элементы.ДеревоНастроекВидОперации;
    ПолеВыбора.СписокВыбора.Очистить();
    
    УровеньСтроки = ПолучитьУровеньСтроки(ТекущаяСтрока);
    
    Если УровеньСтроки = 0 Тогда
        ПолеВыбора.СписокВыбора.Добавить("CashFlow");
    ИначеЕсли УровеньСтроки = 1 Тогда
        ПолеВыбора.СписокВыбора.Добавить("ОборотДТ");
        ПолеВыбора.СписокВыбора.Добавить("ОборотКТ");
    КонецЕсли;
КонецПроцедуры

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

← На главную