Как убрать или заменить стандартное предупреждение «Пометить элемент на удаление?» в 1С

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

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

Почему системный обработчик нельзя просто «отключить»

Рассмотрим природу этого механизма. Вопрос о пометке на удаление — это глубоко интегрированная функция платформы, привязанная к стандартным командам динамического списка и формы объекта. Проблема заключается в том, что событие ПередУдалением, которое мы видим в свойствах динамического списка, срабатывает только при физическом удалении записи из базы данных (обычно это сочетание клавиш Shift + Del). Для модификации реквизита ПометкаУдаления (интерактивная пометка) прямого предопределенного события на уровне формы списка, которое позволило бы легко прервать процесс и выдать свое сообщение, не существует.

Проанализируем ситуацию: если мы просто попытаемся перехватить действие в обработчике ПередЗаписью на уровне модуля объекта, системный вопрос пользователю все равно будет задан до того, как управление передастся в код модуля. Таким образом, единственный эффективный способ — это подмена стандартной команды платформы своей собственной.

Шаг 1. Создание собственной команды формы

Разберем по шагам процесс создания альтернативного механизма в форме списка (например, для справочника «Проекты»):

  1. Откроем форму списка справочника в конфигураторе.
  2. Перейдем на вкладку «Команды» и добавим новую команду, назовем ее УстановитьПометкуУдаленияКастом.
  3. В свойствах команды обязательно заполним поле «Сочетание клавиш». Установим там значение Del (Delete). Это критически важный момент: назначив горячую клавишу, мы перехватываем стандартное поведение клавиатуры, и при нажатии Del будет вызываться наш код, а не системный.
  4. Перетащим команду на командную панель формы или в контекстное меню списка.

Шаг 2. Реализация программной логики пометки

Теперь проанализируем код, который должен выполняться при вызове нашей команды. Нам нужно реализовать асинхронный вызов вопроса, чтобы не блокировать работу интерфейса, и выполнить инверсию пометки удаления. Рассмотрим пример кода:


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

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

На сервере нам необходимо получить объект и программно изменить его состояние:


&НаСервереБезКонтекста
Процедура ИзменитьПометкуНаСервере(СсылкаНаОбъект)
    
    ОбъектМенеджер = СсылкаНаОбъект.ПолучитьОбъект();
    // Инвертируем текущую пометку
    ОбъектМенеджер.ПометкаУдаления = НЕ ОбъектМенеджер.ПометкаУдаления;
    
    Попытка
        ОбъектМенеджер.Записать();
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
КонецПроцедуры

Шаг 3. Отключение стандартной видимости

Чтобы пользователь не мог воспользоваться системной кнопкой (которая все еще может присутствовать в меню «Еще»), выполним следующие действия:

  1. В свойствах элемента формы «Список» (динамический список) найдем состав команд.
  2. Снимем галочку видимости у стандартной команды Пометить на удаление / Снять пометку.
  3. Если работа ведется в крупной конфигурации (например, 1С:ERP), рекомендуется использовать Расширение. В расширении в процедуре ПриСозданииНаСервере можно программно скрыть элемент командной панели:

// Пример для расширения формы
ЭлементСтандартнойКоманды = Элементы.Найти("СписокКонтекстноеМенюПометитьНаУдаление");
Если ЭлементСтандартнойКоманды <> Неопределено Тогда
    ЭлементСтандартнойКоманды.Видимость = Ложь;
КонецЕсли;

Нюансы работы с формой объекта

Посмотрим на ситуацию шире: пользователь может открыть сам проект и попытаться пометить его на удаление из Формы элемента. Наше решение для списка там не сработает. Чтобы добиться единообразия, в форме элемента также следует:

Важное замечание по бизнес-логике

Выясним причину, почему подмены на уровне интерфейса может быть недостаточно. Если ваша задача — запретить пометку на удаление при определенных условиях (например, проект нельзя удалять, если по нему есть движения), то логику проверки обязательно нужно продублировать в модуле объекта в обработчике ПередЗаписью. Это защитит базу от изменений через групповую обработку данных или внешние соединения, где формы списка вообще не используются.

Используем следующий паттерн в модуле объекта:


Процедура ПередЗаписью(Отказ)
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем, что пометка удаления именно устанавливается (была Ложь, стала Истина)
    Если ПометкаУдаления И НЕ Ссылка.ПометкаУдаления Тогда
        // Здесь ваша проверка условий
        Если ЕстьАктивныеЗадачиПоПроекту() Тогда
            ТекстОшибки = "Нельзя помечать на удаление проект, по которому есть незавершенные задачи!";
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки, , , , Отказ);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Резюме

Мы проанализировали системные ограничения платформы и нашли обходной путь. Подведем итог: для замены стандартного вопроса мы используем собственную команду формы с переназначенной клавишей Del, скрываем стандартные элементы интерфейса и обязательно сопровождаем это программной записью объекта с вызовом ОповеститьОбИзменении для корректного обновления динамических списков в других открытых окнах пользователя.

← На главную