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