При разработке интерфейсов на обычных формах 1С часто возникает задача реализовать механизм перетаскивания строк (Drag-and-Drop) из одной таблицы в другую. Однако после включения свойств элементов управления РазрешитьНачалоПеретаскивания у таблицы-источника и РазрешитьПеретаскивание у таблицы-приемника разработчики нередко сталкиваются с тем, что курсор мыши при наведении показывает знак запрета («стоянка запрещена»), а события вставки не срабатывают. Разберем по шагам, как устроен механизм перетаскивания в платформе 1С, почему возникает блокировка и как правильно реализовать перенос данных программно.
Чтобы понять, в какой момент платформа запрещает действие, проанализируем стандартный жизненный цикл перетаскивания в 1С:
НачалоПеретаскивания. В этом событии платформа определяет переносимое значение и маску разрешенных действий (копирование, перемещение).ПроверкаПеретаскивания. Именно оно определяет внешний вид курсора: если обработчик возвращает запрет или не отключает стандартную проверку платформы, пользователь видит пиктограмму запрета.Перетаскивание, где и выполняется фактическая запись данных.ОкончаниеПеретаскивания, где при необходимости удаляется исходная строка (если выполнялось перемещение, а не копирование).Рассмотрим основные причины, из-за которых платформа блокирует перетаскивание между двумя табличными полями:
ПроверкаПеретаскивания и Перетаскивание необходимо явно указывать СтандартнаяОбработка = Ложь;.ДействиеПеретаскивания.Копирование, а в проверке приемника жестко задано ДействиеПеретаскивания.Перемещение, платформа отобразит запрет. В обработчике источника следует явно разрешить нужные действия или использовать комбинацию флагов.ТолькоПросмотр = Истина, либо выключена Доступность, перетаскивание будет заблокировано на уровне интерфейса.Разберем пример реализации переноса строк между двумя табличными полями обработки (ТабличноеПолеИсточник и ТабличноеПолеПриемник).
Шаг 1. Настройка свойств элементов управления
В конфигураторе для ТабличноеПолеИсточник устанавливаем свойство РазрешитьНачалоПеретаскивания в значение Истина. Для ТабличноеПолеПриемник включаем свойство РазрешитьПеретаскивание в значение Истина.
Шаг 2. Обработка начала перетаскивания в источнике
В модуле формы создадим обработчик события НачалоПеретаскивания для исходной таблицы. Передадим структуру переносимых данных и разрешим перемещение:
Процедура ТабличноеПолеИсточникНачалоПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Недоступно;
Возврат;
КонецЕсли;
// Формируем структуру с данными переносимой строки
ДанныеСтроки = Новый Структура;
ДанныеСтроки.Вставить("Номенклатура", ТекущиеДанные.Номенклатура);
ДанныеСтроки.Вставить("Количество", ТекущиеДанные.Количество);
ДанныеСтроки.Вставить("Цена", ТекущиеДанные.Цена);
// Передаем значение и разрешаем перемещение и копирование
ПараметрыПеретаскивания.Значение = ДанныеСтроки;
ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение | ДействиеПеретаскивания.Копирование;
КонецПроцедуры
Шаг 3. Проверка перетаскивания в таблице-приемнике
Создадим обработчик события ПроверкаПеретаскивания для целевого табличного поля. Отключим стандартную обработку, проверим тип данных и сообщим платформе о готовности принять строку:
Процедура ТабличноеПолеПриемникПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
СтандартнаяОбработка = Ложь;
// Проверяем, что переносится ожидаемая структура данных
Если ТипЗнч(ПараметрыПеретаскивания.Значение) = Тип("Структура") Тогда
ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение;
Иначе
ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Недоступно;
КонецЕсли;
КонецПроцедуры
Шаг 4. Обработка вставки данных в приемнике
В событии Перетаскивание принимающей таблицы добавляем новую строку и заполняем ее значениями из переданной структуры:
Процедура ТабличноеПолеПриемникПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
СтандартнаяОбработка = Ложь;
Если ТипЗнч(ПараметрыПеретаскивания.Значение) = Тип("Структура") Тогда
ДанныеСтроки = ПараметрыПеретаскивания.Значение;
НоваяСтрока = ЭтотОбъект.ТабличнаяЧастьПриемник.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ДанныеСтроки);
// Устанавливаем действие, чтобы источник знал о завершении перемещения
ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение;
КонецЕсли;
КонецПроцедуры
Шаг 5. Удаление строки из источника (при необходимости перемещения)
Если требуется физически удалить строку из первой таблицы после успешного переноса, используем событие ОкончаниеПеретаскивания в таблице-источнике:
Процедура ТабличноеПолеИсточникОкончаниеПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
Если ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение Тогда
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
ЭтотОбъект.ТабличнаяЧастьИсточник.Удалить(ТекущиеДанные);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если в процессе разработки вы сталкиваетесь с тем, что табличное поле типа ДеревоЗначений отображает только строки верхнего уровня и не показывает вложенные узлы, обратите внимание на следующие нюансы:
ОтображатьИерархию: у ведущей колонки дерева (как правило, первой) обязательно должен стоять признак ОтображатьИерархию. Без этого флажка пиктограммы раскрытия («плюсики») не отображаются, и дерево визуально выглядит как плоская таблица.
ЭлементыФормы.ТабличноеПолеДерево.Развернуть(СтрокаДерева, Истина);
ТаблицаЗначений на ДеревоЗначений конфигуратор не всегда автоматически перестраивает свойства существующих колонок. В такой ситуации помогает пересоздание колонок через контекстное меню элемента либо создание нового элемента управления с нуля.Таким образом, ключевым условием корректной работы Drag-and-Drop между таблицами на обычных формах является полное переопределение стандартной обработки через СтандартнаяОбработка = Ложь; во всех целевых обработчиках и согласование допустимых действий между источником и приемником.