Можно ли вызвать процедуру общего модуля через метод УстановитьДействие() в 1С

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

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

Техническое ограничение платформы и контекст исполнения

Проанализируем работу метода УстановитьДействие(ИмяСобытия, ИмяПроцедуры). Согласно документации и практике разработки, этот метод принимает в качестве второго параметра строку, содержащую имя процедуры. Ключевая проблема заключается в том, что платформа ищет указанную процедуру исключительно в контексте модуля той формы, для элемента которой вызывается метод.

Даже если процедура в общем модуле помечена как Экспорт, или если общий модуль является глобальным, метод УстановитьДействие() не сможет её "увидеть". Это связано с внутренними механизмами диспетчеризации событий интерфейса. Платформа ожидает, что обработчик события будет находиться в "теле" объекта (формы), который это событие инициирует.

Выясним причину такого поведения. 1С разделяет логику интерфейса (клиентский контекст формы) и бизнес-логику (общие модули). Прямая привязка визуального события к процедуре общего модуля нарушила бы инкапсуляцию формы. Таким образом, ответ на вопрос "появился ли способ вызвать ОМ напрямую" — нет, на текущих релизах платформы (включая 8.3.18 и выше) такой возможности не существует.

Различие между УстановитьДействие() и ОписаниеОповещения

Часто возникает путаница между классическими событиями элементов управления и асинхронными вызовами. Разберем это отличие, чтобы не тратить время на поиск несуществующих функций. Объект ОписаниеОповещения позволяет передать имя процедуры и общий модуль в качестве места поиска этой процедуры:


Оповещение = Новый ОписаниеОповещения("МояПроцедураВОбщемМодуле", ОбщийМодульКлиент);
ПоказатьВопрос(Оповещение, "Текст вопроса", РежимДиалогаВопрос.ДаНет);

К сожалению, метод УстановитьДействие() — это более старый механизм, который работает только со строковыми именами и не поддерживает объект ОписаниеОповещения. Это фундаментальное различие, которое диктует нам необходимость использовать "прослойку" в модуле формы.

Решение: Стратегия «Универсального обработчика»

Посмотрим, как можно реализовать задачу автора темы, максимально сохранив чистоту кода и вынеся логику в общие модули. Если мы меняем форму программно (например, в процедуре ПриСозданииНаСервере общего модуля МодификацияКонфигурацииПереопределяемый), нам все равно придется один раз добавить в форму или в расширение формы небольшую процедуру-диспетчер.

Рассмотрим по шагам, как организовать такую архитектуру:

  1. В модуле формы (через расширение или напрямую в коде конфигурации) создаем одну экспортную процедуру, которая будет принимать событие.
  2. Внутри этой процедуры вызываем наш общий модуль, передавая ему контекст формы и параметры элемента.
  3. При программном создании элементов в общем модуле указываем имя этой "прослойки" в методе УстановитьДействие().

Пример кода в модуле формы:


&НаКлиенте
Процедура УниверсальныйОбработчикСобытия(Элемент) Экспорт
    // Вся логика уходит в общий модуль
    МойОбщийМодульКлиент.ОбработатьСобытиеНаФорме(ЭтаФорма, Элемент);
КонецПроцедуры

Пример программного назначения в общем модуле:


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

Использование программных команд формы

Проанализируем ситуацию, когда нам нужно добавить кнопку. Вместо того чтобы привязывать действие напрямую к элементу, правильнее будет программно создать Команду формы. Это дает больше гибкости, хотя и не избавляет от необходимости процедуры в модуле формы.

Разберем пример создания команды:


// В контексте общего модуля (на сервере)
НоваяКоманда = Форма.Команды.Добавить("ПрограммнаяКоманда");
НоваяКоманда.Действие = "ОбработчикКомандыНаФорме"; // Процедура в модуле формы
НоваяКоманда.Заголовок = "Выполнить действие";

НоваяКнопка = Форма.Элементы.Добавить("КнопкаДействия", Тип("КнопкаФормы"), Форма.Элементы.ОсновнаяПанель);
НоваяКнопка.ИмяКоманды = "ПрограммнаяКоманда";

Как мы видим, свойство Действие у объекта КомандаФормы также принимает только строку, которая должна соответствовать процедуре в модуле формы. Таким образом, "Валенки" (как выразился автор темы) — то есть использование модуля формы — остаются неизбежным инструментом разработчика 1С.

Выводы и рекомендации

Подводя итог, можно сказать, что желание "не размазывать код по формам" абсолютно оправдано с точки зрения качества архитектуры, но платформа 1С диктует свои правила.

Основные выводы нашего анализа:

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

← На главную