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