Как отменить перетаскивание (Drag&Drop) элементов в динамическом списке 1С по условию?

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

При работе с динамическими списками в управляемых формах «1С:Предприятие 8.3» часто возникает необходимость разрешить пользователям интерактивно переносить элементы и группы с помощью мыши (механизм Drag&Drop). Однако из-за случайных движений мыши пользователи могут ошибочно изменить родителя у справочника или группы. В этой статье разберем, как правильно перехватить завершение перетаскивания, спросить у пользователя подтверждение или отменить действие при выполнении определенных условий.

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

Частая ошибка разработчиков заключается в попытке отменить интерактивный перенос в событии ОкончаниеПеретаскивания. К моменту вызова этого события системная обработка источника уже завершена, и установка параметра СтандартнаяОбработка = Ложь не приведет к отмене изменения данных в базе.

Для правильной обработки отмены необходимо ориентироваться на следующую цепочку событий таблицы формы:

  1. НачалоПеретаскивания — вызывается в источнике при старте захвата объекта мышью.
  2. ПроверкаПеретаскивания — срабатывает постоянно при перемещении курсора над таблицей-приемником. Позволяет визуально запретить сброс (показывает знак «запрещено»).
  3. Перетаскивание — возникает в приемнике в момент отпускания кнопки мыши. Это именно та точка, где нужно отменять стандартную обработку и запрашивать подтверждение.
  4. ОкончаниеПеретаскивания — вызывается в источнике после того, как перенос физически завершен.

Разберем подробнее, как реализовать диалог подтверждения с помощью события Перетаскивание.

Пошаговый алгоритм реализации запроса подтверждения (Да/Нет)

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

Поэтому применяют следующий подход: в событии Перетаскивание всегда отменяют стандартную обработку, а сам перенос выполняют программно после получения положительного ответа от пользователя.

  1. Перехват события на клиенте: В событии таблицы формы Перетаскивание устанавливаем СтандартнаяОбработка = Ложь. Это блокирует автоматическое изменение родителя платформой. Считываем перетаскиваемые данные из ПараметрыПеретаскивания.Значение и целевую строку Строка.

  2. Вызов асинхронного диалога: Формируем процедуру-обработчик оповещения и вызываем ПоказатьВопрос.

  3. Запись изменений на сервере: Если пользователь выбирает ответ «Да», передаем данные в серверную процедуру, меняем реквизит Родитель у перетаскиваемого объекта, записываем его и обновляем динамический список методами Обновить() или Прочитать().

Рассмотрим пример реализации на языке 1С:


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

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

&НаКлиенте
Процедура ПослеОтветаНаВопросОПереносе(Результат, ДополнительныеПараметры) Экспорт

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

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

&НаСервере
Процедура ПереместитьЭлементНаСервере(СсылкаНаОбъект, СсылкаНаНовогоРодителя)
    
    ОбъектСправочника = СсылкаНаОбъект.ПолучитьОбъект();
    ОбъектСправочника.Родитель = СсылкаНаНовогоРодителя;
    
    Попытка
        ОбъектСправочника.Записать();
    Исключение
        ВызватьИсключение НСтр("ru = 'Не удалось переместить элемент: '") + ОписаниеОшибки();
    КонецПопытки;

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

Предварительная проверка валидности переноса

Чтобы пользователь не мог даже отпустить мышь над некорректным родителем (например, попытка перенести папку саму в себя или в подчиненный элемент), проанализируем событие ПроверкаПеретаскивания.

В этом событии мы можем заранее сменить состояние курсора на «запрещено», установив действие перетаскивания:


&НаКлиенте
Процедура СписокПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    
    // Если перенос выполняется в пустую область или целевая строка недопустима
    Если Строка = Неопределено Тогда
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Отмена;
    КонецЕсли;

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

Альтернативные способы защиты от случайных переносов

Если пользователи часто совершают ошибочные действия мышью, рассмотрим еще два практических варианта решения проблемы:

  1. Переключатель режима перетаскивания: На форму выводится флажок (тумблер) РазрешитьПеретаскивание. В событии формы при изменении этого флажка меняются свойства таблицы РазрешитьПеретаскивание и РазрешитьНачалоПеретаскивания. После завершения операции флажок автоматически снимается.
  2. Отказ от Drag&Drop в пользу команды: Свойства интерактивного перетаскивания отключаются полностью. Для перемещения элементов добавляется команда формы «Переместить в группу», которая вызывает стандартную форму выбора группы с последующей проверкой прав и подтверждением.
← На главную