Попробуем разобраться с условной задачей перемещение по строкам таблицы вверх-вниз при размещении реквизита типа дерево на форме.
Реквизит типа ДанныеФормыДерево напрямую нельзя связать ни с каким из ссылочных типов данных. Для вывода данных, например, табличной части в дерево, потребуется данные табличной части сначала выгрузить в дерево, а по окончании редактирования загрузить обратно. При этом в список реквизитов, например, обработки можно добавить реквизит типа Дерево значений, но реквизиты обработки не сохраняются в информационной базе и существовать такой реквизит будет только пока обработка открыта.
Итак, реквизит для отображения дерева имеет тип ДанныеФормыДерево и является коллекцией элементов типа ДанныеФормыЭлементДерева.
Рассмотрим общие черты и различия реквизиты типа ДанныеФормыДерево и реквизиты типа ДанныеФормыКоллекция.
ДанныеФормыДерево | ДанныеФормыКоллекция |
Каждая строка (элемент коллекции) имеет свой уникальный идентификатор, не изменяющийся при любых изменениях формы (кроме удаления строки). Идентификатор строки в обоих случаях может быть получен ПолучитьИдентификатор(). Для обоих коллекций можно однозначно найти строку методом НайтиПоИдентификатору() | |
Реквизиты обоих типов представляются на форме в виде элемента типа Таблица, но с учетом особенностей типа реквизита | |
Есть возможность получить доступ к подчиненным строке элементам, а так же его родителю | |
Есть свойство НомерСтроки | |
Получить строки напрямую можно только в пределах текущего уровня | Возможно получение любой строки |
Индекс уникален только в пределах подчинения. Метод Количество() выдает количество элементов для текущего уровня | Индекс уникален для всех строк. Метод Количество() возвращает общее количество |
Есть методы Итог() и Сортировать() | |
Выгружать/загружать напрямую можно только для связанных значений типа ДеревоЗначений можно загрузить/выгрузить колонку в массив. В ДеревоЗначений можно выгрузить, например, результат запроса или результаты СКД | Можно загружать/выгружать данные как напрямую, так и для связанных значений: таблиц значений / табличных частей |
Элемент формы Таблица, связанный с соответствующим типом.
ДанныеФормыДерево | ДанныеФормыКоллекция |
Идентификатор однозначно связывает со строкой реквизита - ЭлементКоллекции или ДанныеФормыЭлементДерева | |
Можно получить идентификатор текущей строки Можно установить текущую строку по идентификатору |
|
Можно получить/установить родителя элемента - свойство ТекущийРодитель (согласно документации допускается чтение и запись). Лично у меня на 8.3.23.2157 получить родителя таким образом не получилось, всегда возвращалось Неопределено | |
Структуру дерева можно свернуть-развернуть Свернуть(Идентификатор) Развернуть(Идентификатор) |
Отдельно хочется отметить "несовершенство" стандартных интерактивных функций таблицы для дерева. В пустой таблице можно добавить элемент "в корень" таблицы по нажатии кнопки Добавить. Следующее добавление произойдет в подчиненный предыдущему элементу. Добавить новый элемент "в корень" у меня не получилось.
Основные правила "навигации" по реквизиту формы Дерево типа ДанныеФормыДерево.
1. Получить элементы "корня" Дерево.ПолучитьЭлементы(). Метод ПолучитьРодителя() для любого элемента "корня" будет возвращать Неопределено
2. Для произвольного элемента возможно:
2.1. Получить родителя = ПолучитьРодителя()
2.2. Получить дочерние элементы = ПолучитьЭлементы()
2.3. Получить "соседние" элементы того же уровня = ПолучитьРодителя().ПолучитьЭлементы()
3. Для получения списка родителей / родителя верхнего уровня следует рекурсивно получать родителей вышестоящего элемента. Как было сказано выше, для родителя самого верхнего уровня ПолучитьРодителя() возвращает Неопределено.
Как и в "прошлой серии" привожу код процедуры движение текущей строки вниз в пределах подчинения.
Опция Вокруг определяет действие при достижении последней строки. Если Истина, то текущей становится первая строка, если Ложь, то ничего не изменяется.
&НаКлиенте
Процедура Вниз(Команда)
Идентификатор = Элементы.Дерево.ТекущаяСтрока;
Если Дерево.НайтиПоИдентификатору(Идентификатор).ПолучитьРодителя() = Неопределено Тогда
ТекущийУровеньДерева = Дерево.ПолучитьЭлементы();
Иначе
ТекущийУровеньДерева = Дерево.НайтиПоИдентификатору(Идентификатор).ПолучитьРодителя().ПолучитьЭлементы();
//Определяется получением дочерних элементов от родителя текущего элемента
КонецЕсли;
Индекс = ТекущийУровеньДерева.Индекс(Дерево.НайтиПоИдентификатору(Идентификатор));
Если Индекс < ТекущийУровеньДерева.Количество()-1 Тогда
НовыйИдентификатор = ТекущийУровеньДерева[Индекс+1].ПолучитьИдентификатор();
Иначе
Если Вокруг Тогда
НовыйИдентификатор =ТекущийУровеньДерева[0].ПолучитьИдентификатор();
Иначе
НовыйИдентификатор = Идентификатор; // А можно проще - написать Возврат, ведь ничего делать не нужно
КонецЕсли;
КонецЕсли;
Элементы.Дерево.ТекущаяСтрока = НовыйИдентификатор;
КонецПроцедуры
Разрабатывалось и тестировалось на 23-м релизе 8.3.23.2157. Поскольку "новые" методы здесь не используются, можно с уверенностью сказать, что обработка будет функционировать под любым релизом платформы на управляемых формах.