Управляемая форма 1С 8.2(8.3) – работа с деревом значений и таблицей значений. Часть II (Реализация DRAG and DROP)

Публикация № 356658

Программирование - Практика программирования

1с 8.2 1с 8.3 Дерево значений Таблица значений Управляемые формы

16
Реализация механизма Drag and Drop (или, проще говоря, “Перетаскивания”) для ДереваЗначений, расположенного на управляемой форме управляемого приложения 1С 8.2

Эта статья является продолжением статьи «Управляемая форма 1С 8.2(8.3) – Работа с деревом значений и таблицей значений. Часть I (Основы)», она будет посвящена реализации механизма Drag and Drop (или, проще говоря, “Перетаскивания”) для ДереваЗначений, расположенного на управляемой форме управляемого приложения 1С 8.2

Основная сложность реализации механизма перетаскивания заключается в том, что у строки ДереваЗначений платформа не позволяет просто изменить родителя, т.е. переподчинить строку. Единственный способ это сделать – создать новую строку вместе со всеми подчиненными строками, т.е. полностью скопировать всю ветку дерева вместе со всей иерархией и подчинить ее требуемой строке-родителю, после чего удалить исходную ветку. Данная задача распадается на две подзадачи:
1). Перед перетаскиванием необходимо проверить корректность данной операции, узел дерева нельзя переносить в узлы, подчиненные ему самому, т.е. родительский узел нельзя переносить в дочерние, т.к. это приведет к “бесконечной рекурсии” и “падению” платформы. Это реализуется с помощью обработчика события ЭлементДеревоПроверкаПеретаскивания(…)
2). Если перетаскивание возможно, то при помощи обработчика ЭлементДеревоПеретаскивание(…) запускается рекурсивная функция, которая создает новую ветку дерева, подчиненную требуемому родителю, а исходную удаляет.

Обращаю особое внимание на то, что в платформе 8.2 реализован механизм множественного выбора элементов, поэтому вышеуказанные операции необходимо произвести для всех выбранных пользователем элементов.

 

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Создание и заполнение "обычного" объекта прикладного типа ДеревоЗначений,
    // который будет отображен на управляемой форме
    ДеревоОбъект = Новый ДеревоЗначений;
    ДеревоОбъект.Колонки.Добавить("Узел", Новый ОписаниеТипов("Строка"));
    Для к1 = 1 По 3 Цикл
        СтрокаУ1 = ДеревоОбъект.Строки.Добавить();
        СтрокаУ1.Узел = "Узел"+к1;
        Для к2 = 1 По 3 Цикл
            СтрокаУ2 = СтрокаУ1.Строки.Добавить();
            СтрокаУ2.Узел = СтрокаУ1.Узел+к2;
            Для к3 = 1 По 3 Цикл
                СтрокаУ3 = СтрокаУ2.Строки.Добавить();
                СтрокаУ3.Узел = СтрокаУ2.Узел+к3;
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;

    // Создание Реквизита формы типа ДанныеФормыДерево
    МассивДобавляемыхРеквизитов = Новый Массив;
    МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Дерево", Новый ОписаниеТипов("ДеревоЗначений")));
    Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
        МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, "Дерево"));
    КонецЦикла;
    ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);

    // Преобразование объекта прикладного типа ДеревоЗначений
    // в реквизит управляемой формы (данные формы)
    ЗначениеВРеквизитФормы(ДеревоОбъект, "Дерево");

    // Создание элемента формы типа ТаблицаФормы для отображения дерева
    ЭлементДерево = Элементы.Добавить("Дерево", Тип("ТаблицаФормы"));
    ЭлементДерево.ПутьКДанным = "Дерево";
    ЭлементДерево.Отображение = ОтображениеТаблицы.Дерево;

    Для Каждого Колонка Из ДеревоОбъект.Колонки Цикл
        НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"), ЭлементДерево);
        НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
        НовыйЭлемент.ПутьКДанным = "Дерево." + Колонка.Имя;
    КонецЦикла;

    // Добавим обработчики и установим свойства
    ЭлементДерево.МножественныйВыбор=Истина;
    ЭлементДерево.РазрешитьПеретаскивание=Истина;
    ЭлементДерево.РазрешитьНачалоПеретаскивания=Истина;
    ЭлементДерево.УстановитьДействие("ПроверкаПеретаскивания", "ЭлементДеревоПроверкаПеретаскивания");
    ЭлементДерево.УстановитьДействие("Перетаскивание", "ЭлементДеревоПеретаскивание");

КонецПроцедуры

&НаКлиенте
Функция ПроверитьВозможностьПереноса(ПереносимыйЭлемент, Знач НовыйРодитель)

    Пока НЕ НовыйРодитель = Неопределено Цикл
        Если ПереносимыйЭлемент = НовыйРодитель Тогда
            Возврат Ложь;
        КонецЕсли;
        НовыйРодитель = НовыйРодитель.ПолучитьРодителя();
    КонецЦикла;

    Возврат Истина;

КонецФункции

&НаКлиенте
Функция СкопироватьСтрокуДерева(РеквизитДерево, Приемник, Источник)

    Перем НоваяСтрока, ОбратныйИндекс, КолПодчиненныхСтрок;

    // Источник может быть уже перенесен
    // Это произходит если выделены несколько элементов
    // одной и той же ветви дерева на разных уровнях иерархии
    Если Источник = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;

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

    ЗаполнитьЗначенияСвойств(НоваяСтрока, Источник);

    КолПодчиненныхСтрок = Источник.ПолучитьЭлементы().Количество();
    Для ОбратныйИндекс = 1 По КолПодчиненныхСтрок Цикл
        ПодчиненнаяСтрока = Источник.ПолучитьЭлементы()[КолПодчиненныхСтрок - ОбратныйИндекс];
        СкопироватьСтрокуДерева(РеквизитДерево, НоваяСтрока, ПодчиненнаяСтрока);
    КонецЦикла;

    Если Источник.ПолучитьРодителя() = Неопределено Тогда
        РеквизитДерево.ПолучитьЭлементы().Удалить(Источник);
    Иначе
        Источник.ПолучитьРодителя().ПолучитьЭлементы().Удалить(Источник);
    КонецЕсли;

    Возврат НоваяСтрока;

КонецФункции

&НаКлиенте
Процедура ЭлементДеревоПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)

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

    СтандартнаяОбработка = Ложь;

    РеквизитДерево = ЭтаФорма["Дерево"];

    ИДНовыйРодитель = Строка;
    // Если НовыйРодитель = Неопределено => Корень дерева
    НовыйРодитель = ?(ИДНовыйРодитель = Неопределено, Неопределено, РеквизитДерево.НайтиПоИдентификатору(ИДНовыйРодитель));

    МассивИДПереносимыхЭлементов = ПараметрыПеретаскивания.Значение;

    Для каждого ИДПереносимыйЭлемент из МассивИДПереносимыхЭлементов Цикл

        ПереносимыйЭлемент = РеквизитДерево.НайтиПоИдентификатору(ИДПереносимыйЭлемент);

        Если НЕ ПроверитьВозможностьПереноса(ПереносимыйЭлемент, НовыйРодитель) Тогда
            ПараметрыПеретаскивания.Действие=ДействиеПеретаскивания.Отмена;
            Прервать;
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

&НаКлиенте
Процедура ЭлементДеревоПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)

    СтандартнаяОбработка=Ложь;

    РеквизитДерево = ЭтаФорма["Дерево"];

    ИДПриемник = Строка;
    // Если ИДПриемник = Неопределено => Корень дерева
    Приемник = ?(ИДПриемник = Неопределено, Неопределено, РеквизитДерево.НайтиПоИдентификатору(ИДПриемник));

    МассивИДИсточник = ПараметрыПеретаскивания.Значение;

    Для Каждого ИДИсточник Из МассивИДИсточник Цикл
        Источник = РеквизитДерево.НайтиПоИдентификатору(ИДИсточник);
        НоваяСтрока = СкопироватьСтрокуДерева(РеквизитДерево, Приемник, Источник);
        // Производится копирование в корень
        // Для "красоты" развернем вновь созданную ветвь
        Если Приемник = Неопределено и НоваяСтрока<>Неопределено Тогда
            Элементы["Дерево"].Развернуть(НоваяСтрока.ПолучитьИдентификатор(), Истина);
        КонецЕсли;
    КонецЦикла;

    // Для "красоты" развернем ветвь-родителя
    Если НЕ Приемник = Неопределено Тогда
        Элементы["Дерево"].Развернуть(ИДПриемник, Истина);
    КонецЕсли;

КонецПроцедуры


http://www.obrabotki.com/1s-tree-table-managedforms-2/

16

Скачать файлы

Наименование Файл Версия Размер
Пример к статье
.rar 4,42Kb
24.06.15
19
.rar 4,42Kb 19 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Рейтинг
1. ЧерныйКот 27.02.17 14:15 Сейчас в теме
Спасибо, полезно!
Только не понял про ОбратныйИндекс, зачем он?
Оставьте свое сообщение