При разработке в расширениях «1С:Предприятие 8.3» программисты часто сталкиваются с задачей динамического изменения интерфейса. Типичный пример — необходимость добавить на форму элемента справочника или документа поле для отображения логотипа контрагента, фотографии сотрудника или изображения номенклатуры. Однако при программном создании элементов интерфейса возникает серьезное препятствие: привязка обработчиков событий (таких как нажатие или изменение) часто не срабатывает, возвращая стандартные системные окна вместо вызова кастомного кода.
В этой статье мы подробно разберем, почему платформа ведет себя подобным образом, как правильно связать динамический элемент формы с кодом в расширении, а также рассмотрим несколько альтернативных способов решения этой задачи.
В управляемом приложении 1С метод УстановитьДействие (или свойство Действие у программно добавляемых команд) имеет жесткое платформенное ограничение. В качестве второго параметра этот метод принимает исключительно строковое имя экспортируемой процедуры, расположенной строго в модуле самой этой формы.
Попытка передать туда конструкцию вида "ИмяОбщегоМодуля.ИмяПроцедуры" или настроить вызов процедуры, находящейся в общем модуле расширения, ни к чему не приведет. Платформа просто проигнорирует этот вызов или выдаст ошибку, так как контекст исполнения события жестко изолирован внутри конкретной формы. Именно поэтому у автора темы нажатие по картинке вызывало стандартное системное окно, а не его кастомную процедуру.
Для решения этой проблемы существует три основных метода. Разберем их по шагам.
---
Наиболее надежный и стандартный способ — заимствовать целевую форму в расширение, чтобы получить доступ к ее модулю, но сделать это максимально «аккуратно», чтобы не усложнить будущие обновления конфигурации.
Многие разработчики боятся переносить формы в расширение, предполагая, что это повлечет за собой заимствование всех связанных реквизитов и перегрузит конфигурацию. На самом деле существует безопасная методика «легкого заимствования»:
ФормаЭлемента справочника Контрагенты) в расширение.После этого мы можем переходить к написанию кода. Реализуем программное добавление реквизита, элемента формы и подключение события.
Шаг 1. В общем модуле расширения перехватываем событие создания формы на сервере с помощью аннотации &После:
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
// Проверяем, что работаем с нужной формой
Если Форма.ИмяФормы = "Справочник.Контрагенты.Форма.ФормаЭлемента" Тогда
// 1. Создаем и добавляем новый реквизит формы для хранения пути к картинке
ДобавляемыеРеквизиты = Новый Массив;
РеквизитЛоготип = Новый РеквизитФормы("Расш1_Логотип", Новый ОписаниеТипов("Строка"), , "Логотип");
ДобавляемыеРеквизиты.Добавить(РеквизитЛоготип);
Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
// 2. Программно создаем элемент формы "ПолеКартинки"
Элементы = Форма.Элементы;
// Добавляем элемент в существующую на форме группу (например, ГруппаОбщаяИнформация)
ЭлементКартинка = Элементы.Добавить("Расш1_Логотип", Тип("ПолеФормы"), Элементы.ГруппаОбщаяИнформация);
ЭлементКартинка.Вид = ВидПоляФормы.ПолеКартинки;
ЭлементКартинка.ПутьКДанным = "Расш1_Логотип";
ЭлементКартинка.Заголовок = "Логотип контрагента";
ЭлементКартинка.Гиперссылка = Истина;
ЭлементКартинка.Доступность = Истина;
ЭлементКартинка.Видимость = Истина;
// 3. Связываем событие "Нажатие" с процедурой, которую мы разместим в модуле заимствованной формы
ЭлементКартинка.УстановитьДействие("Нажатие", "Расш1_ЛоготипНажатие");
КонецЕсли;
КонецПроцедуры
Шаг 2. В модуле нашей заимствованной («легкой») формы в расширении пишем клиентские обработчики для работы с файлом картинки. Будем использовать современные асинхронные методы платформы 1С:
&НаКлиЕнте
Процедура Расш1_ЛоготипНажатие(Элемент, СтандартнаяОбработка)
// Отменяем стандартное поведение платформы
СтандартнаяОбработка = Ложь;
// Создаем описание оповещения для обработки выбора файла
ОписаниеОповещения = Новый ОписаниеОповещения("Расш1_ОбработатьВыборФайлаКартинки", ЭтотОбъект);
// Настраиваем диалог выбора файла изображения
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогОткрытияФайла.Фильтр = "Файлы картинок (*.jpg;*.png;*.jpeg)|*.jpg;*.png;*.jpeg";
ДиалогОткрытияФайла.Заголовок = "Выберите файл логотипа для загрузки";
ДиалогОткрытияФайла.ПредварительныйПросмотр = Истина;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
// Запускаем асинхронное помещение файла во временное хранилище
НачатьПомещениеФайлов(ОписаниеОповещения, , ДиалогОткрытияФайла, Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура Расш1_ОбработатьВыборФайлаКартинки(ПомещенныеФайлы, ДопПараметры) Экспорт
// Проверяем, выбрал ли пользователь файл
Если ПомещенныеФайлы = Неопределено Или ПомещенныеФайлы.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Получаем адрес временного хранилища, куда платформа поместила файл
АдресКартинкиВХранилище = ПомещенныеФайлы[0].Хранение;
// Записываем адрес в наш реквизит формы, чтобы картинка отобразилась на форме
ЭтотОбъект.Расш1_Логотип = АдресКартинкиВХранилище;
// Сигнализируем системе, что данные формы были изменены
ЭтотОбъект.Модифицированность = Истина;
КонецПроцедуры
Благодаря этому решению код отрабатывает безупречно. При нажатии на область картинки открывается стандартный диалог операционной системы, пользователь выбирает изображение, и оно мгновенно выводится в поле формы.
---
Рассмотрим альтернативную ситуацию: что делать, если вам категорически запрещено заимствовать форму в расширение? В платформе 1С есть интересная возможность обойти это ограничение с помощью элемента ДекорацияФормы.
Вместо элемента ПолеФормы с видом ПолеКартинки мы можем программно создать декорацию-картинку и использовать механизм навигационных ссылок. Платформа умеет обрабатывать нажатия на такие ссылки самостоятельно, минуя необходимость писать код в модуле формы.
Проанализируем пример реализации такого подхода в общем модуле расширения:
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
Если Форма.ИмяФормы = "Справочник.Контрагенты.Форма.ФормаЭлемента" Тогда
Элементы = Форма.Элементы;
// Создаем декорацию формы типа Картинка
ЭлементДекорация = Элементы.Добавить("Расш1_ДекорацияЛоготип", Тип("ДекорацияФормы"), Элементы.ГруппаОбщаяИнформация);
ЭлементДекорация.Вид = ВидДекорацииФормы.Картинка;
// Устанавливаем стандартную картинку из библиотеки или адрес из базы данных
ЭлементДекорация.Картинка = БиблиотекаКартинок.ВыбратьФайл;
ЭлементДекорация.Гиперссылка = Истина;
// Указываем навигационную ссылку. При клике платформа выполнит переход или вызовет команду.
// Это может быть ссылка на внешнюю обработку, команду БСП или элемент файлового хранилища.
ЭлементДекорация.НавигационнаяСсылка = "e1cib/app/Справочник.ШаблоныСообщений...";
КонецЕсли;
КонецПроцедуры
Этот способ имеет ограничения по логике обработки события, но идеально подходит для задач в стиле «открыть файл по клику» или «перейти по ссылке», полностью исключая необходимость расширения модулей форм.
---
Если ваша конфигурация разработана на современной ERP 2.5, Комплексной автоматизации или Управлении торговлей, то в ней гарантированно используется БСП. Практически на каждой управляемой форме этих конфигураций уже присутствует встроенный механизм динамического подключения команд.
Мы можем интегрировать свою команду выбора картинки в штатный механизм БСП, используя переопределяемые общие модули конфигурации (например, ПриОпределенииКомандПодключенныхКОбъектам). Схема работы выглядит следующим образом:
Подключаемый_ВыполнитьКоманду.Этот метод является наиболее методологически верным с точки зрения стандартов разработки фирмы «1С» для типовых конфигураций, так как он полностью исключает ручное заимствование форм и написание кода «в обход» стандартов БСП.
---
Резюмируем, какой из подходов выбрать в зависимости от ваших задач:
| Метод решения | Плюсы | Минусы |
|---|---|---|
| «Легкое» заимствование формы | Полная свобода написания кода на клиенте, поддержка любых асинхронных диалогов и сложных обработчиков. | Форма все же заимствуется в расширение (хотя и в минимальном объеме). |
| Декорация с навигационной ссылкой | Не требует заимствования формы вообще, создается полностью «на лету» из общего модуля. | Ограниченный функционал интерактивного взаимодействия. |
| Подключаемые команды БСП | Соответствие стандартам 1С совместимо, стабильность при любых масштабных обновлениях ERP. | Требует детального понимания архитектуры БСП и написания интеграционного кода. |
Используя предложенные методики, вы сможете эффективно решать задачи по динамическому управлению интерфейсом в расширениях 1С, сохраняя чистоту кода и обеспечивая легкую поддержку ваших конфигураций.