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