При работе в среде 1С:Предприятие 8.3 разработчики часто сталкиваются с необходимостью кастомизации стандартного поведения платформы. Одной из таких задач является изменение или полное отключение системного вопроса: «Пометить элемент на удаление?», который появляется при нажатии клавиши Del или соответствующей кнопки в командной панели. В этой статье мы подробно разберем, почему стандартные события формы не помогают решить эту задачу напрямую, и реализуем надежный механизм замены этого диалога на собственный.
Рассмотрим природу этого механизма. Вопрос о пометке на удаление — это глубоко интегрированная функция платформы, привязанная к стандартным командам динамического списка и формы объекта. Проблема заключается в том, что событие ПередУдалением, которое мы видим в свойствах динамического списка, срабатывает только при физическом удалении записи из базы данных (обычно это сочетание клавиш Shift + Del). Для модификации реквизита ПометкаУдаления (интерактивная пометка) прямого предопределенного события на уровне формы списка, которое позволило бы легко прервать процесс и выдать свое сообщение, не существует.
Проанализируем ситуацию: если мы просто попытаемся перехватить действие в обработчике ПередЗаписью на уровне модуля объекта, системный вопрос пользователю все равно будет задан до того, как управление передастся в код модуля. Таким образом, единственный эффективный способ — это подмена стандартной команды платформы своей собственной.
Разберем по шагам процесс создания альтернативного механизма в форме списка (например, для справочника «Проекты»):
УстановитьПометкуУдаленияКастом.Del (Delete). Это критически важный момент: назначив горячую клавишу, мы перехватываем стандартное поведение клавиатуры, и при нажатии Del будет вызываться наш код, а не системный.Теперь проанализируем код, который должен выполняться при вызове нашей команды. Нам нужно реализовать асинхронный вызов вопроса, чтобы не блокировать работу интерфейса, и выполнить инверсию пометки удаления. Рассмотрим пример кода:
&НаКлиенте
Процедура УстановитьПометкуУдаленияКастом(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Формируем текст своего кастомного вопроса
ТекстВопроса = "Внимание! Вы собираетесь изменить статус пометки на удаление для проекта: " + ТекущиеДанные.Наименование + ". Продолжить?";
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВопросаОПометке", ЭтотОбъект, ТекущиеДанные.Ссылка);
ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОПометке(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Вызываем серверный метод для изменения пометки
ИзменитьПометкуНаСервере(ДополнительныеПараметры);
// Обновляем список, чтобы пользователь сразу увидел изменения
ОповеститьОбИзменении(Тип("СправочникСсылка.Проекты"));
КонецЕсли;
КонецПроцедуры
На сервере нам необходимо получить объект и программно изменить его состояние:
&НаСервереБезКонтекста
Процедура ИзменитьПометкуНаСервере(СсылкаНаОбъект)
ОбъектМенеджер = СсылкаНаОбъект.ПолучитьОбъект();
// Инвертируем текущую пометку
ОбъектМенеджер.ПометкаУдаления = НЕ ОбъектМенеджер.ПометкаУдаления;
Попытка
ОбъектМенеджер.Записать();
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Чтобы пользователь не мог воспользоваться системной кнопкой (которая все еще может присутствовать в меню «Еще»), выполним следующие действия:
Пометить на удаление / Снять пометку.ПриСозданииНаСервере можно программно скрыть элемент командной панели:
// Пример для расширения формы
ЭлементСтандартнойКоманды = Элементы.Найти("СписокКонтекстноеМенюПометитьНаУдаление");
Если ЭлементСтандартнойКоманды <> Неопределено Тогда
ЭлементСтандартнойКоманды.Видимость = Ложь;
КонецЕсли;
Посмотрим на ситуацию шире: пользователь может открыть сам проект и попытаться пометить его на удаление из Формы элемента. Наше решение для списка там не сработает. Чтобы добиться единообразия, в форме элемента также следует:
ИспользоватьСтандартныеКоманды или конкретно скрыть кнопку удаления).Выясним причину, почему подмены на уровне интерфейса может быть недостаточно. Если ваша задача — запретить пометку на удаление при определенных условиях (например, проект нельзя удалять, если по нему есть движения), то логику проверки обязательно нужно продублировать в модуле объекта в обработчике ПередЗаписью. Это защитит базу от изменений через групповую обработку данных или внешние соединения, где формы списка вообще не используются.
Используем следующий паттерн в модуле объекта:
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, что пометка удаления именно устанавливается (была Ложь, стала Истина)
Если ПометкаУдаления И НЕ Ссылка.ПометкаУдаления Тогда
// Здесь ваша проверка условий
Если ЕстьАктивныеЗадачиПоПроекту() Тогда
ТекстОшибки = "Нельзя помечать на удаление проект, по которому есть незавершенные задачи!";
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки, , , , Отказ);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Мы проанализировали системные ограничения платформы и нашли обходной путь. Подведем итог: для замены стандартного вопроса мы используем собственную команду формы с переназначенной клавишей Del, скрываем стандартные элементы интерфейса и обязательно сопровождаем это программной записью объекта с вызовом ОповеститьОбИзменении для корректного обновления динамических списков в других открытых окнах пользователя.