В процессе разработки интерфейсов на платформе 1С:Предприятие 8 (особенно в режиме управляемого приложения) часто возникает необходимость динамического формирования элементов управления. Если создание кнопок для локальных команд формы не вызывает трудностей, то при попытке привязать кнопку к глобальной (или общей) команде разработчики сталкиваются с серьезным системным ограничением.
В этой статье мы подробно разберем, почему возникает эта сложность, проанализируем ограничения платформы и рассмотрим два надежных способа программного вызова глобальных команд: универсальный метод через «команду-обертку» и стандартный подход с использованием Библиотеки Стандартных Подсистем (БСП).
При интерактивном проектировании формы в конфигураторе мы можем легко перетащить любую команду из ветки Глобальные команды на командную панель формы. Платформа автоматически берет на себя все заботы по связыванию элемента интерфейса и исполняемого кода.
Однако при попытке повторить это действие программно в коде модуля формы мы сталкиваемся с тем, что свойство ИмяКоманды (CommandName) объекта КнопкаФормы жестко ограничено. Оно может содержать только имя локальной команды формы, определенной в контексте данного конкретного окна.
Если мы попытаемся напрямую присвоить свойству имя общей команды, например:
// Попытка прямого назначения вызовет ошибку выполнения!
НоваяКнопка.ИмяКоманды = "ОбщаяКоманда.ИмяВашейОбщейКоманды";
Информационная база вернет ошибку: «Недопустимое значение атрибута контекста (ИмяКоманды)». Платформа не умеет напрямую связывать физическую кнопку формы с глобальным контекстом метаданных в обход механизма локальных команд.
Для обхода этого ограничения мы можем использовать два проверенных практикой сценария решения.
Суть данного метода заключается в создании промежуточного звена. Мы программно создаем локальную команду формы, связываем с ней создаваемую кнопку, а уже в обработчике этой локальной команды на клиенте осуществляем переход к глобальной команде через специальный механизм навигационных ссылок.
Давайте по шагам разберем реализацию этого способа.
Шаг 1. Программное создание элементов на сервере
В процедуре ПриСозданииНаСервере мы динамически добавляем команду в коллекцию команд формы, настраиваем ее свойства и создаем саму кнопку на командной панели:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Создаем уникальное имя для нашей локальной команды-посредника
ИмяЛокальнойКоманды = "ПодключаемаяЛокальнаяКоманда_СравнениеБУНУ";
// 2. Добавляем команду в коллекцию команд управляемой формы
НоваяКоманда = Команды.Добавить(ИмяЛокальнойКоманды);
НоваяКоманда.Заголовок = "Сравнение БУ/НУ";
// Указываем имя клиентской процедуры-обработчика, которая будет вызвана при нажатии
НоваяКоманда.Действие = "Подключаемый_ВыполнитьСравнениеБУНУ";
// 3. Создаем кнопку и размещаем ее в командной панели формы (например, ГруппаКоманд)
НоваяКнопка = Элементы.Добавить("Кнопка_СравнениеБУНУ", Тип("КнопкаФормы"), Элементы.ГруппаКоманд);
// Связываем кнопку с нашей локальной командой
НоваяКнопка.ИмяКоманды = ИмяЛокальнойКоманды;
КонецПроцедуры
Шаг 2. Вызов глобальной команды в обработчике на клиенте
Теперь опишем клиентскую процедуру, имя которой мы указали в свойстве Действие. Для вызова глобальной команды мы применим метод ПерейтиПоНавигационнойСсылке. Каждая глобальная команда в системе имеет свой уникальный внутренний адрес URL.
&НаКлиенте
Процедура Подключаемый_ВыполнитьСравнениеБУНУ(Команда)
// Шаблон навигационной ссылки для вызова глобальной команды отчета:
// e1cib/command/Отчет.<ИмяОтчета>.Команда.<ИмяКоманды>
НавСсылка = "e1cib/command/Отчет.ОтчетСравненияБУНУ.Команда.СравнениеБУНУ";
// Переходим по ссылке, что инициирует выполнение глобальной команды
ПерейтиПоНавигационнойСсылке(НавСсылка);
КонецПроцедуры
Если вам требуется вызвать не команду конкретного отчета, а независимую общую команду, формат формирования навигационной ссылки будет выглядеть следующим образом:
НавСсылка = "e1cib/command/ОбщаяКоманда.ИмяВашейОбщейКоманды";
ПерейтиПоНавигационнойСсылке(НавСсылка);
Важное примечание о передаче параметров:
В реальных задачах глобальные команды часто должны выполняться в контексте определенного объекта (например, конкретного договора, контрагента или документа). В этом случае в навигационную ссылку необходимо передать параметр в виде уникального идентификатора ссылки этого объекта:
&НаКлиенте
Процедура Подключаемый_ВыполнитьПараметризованнуюКоманду(Команда)
Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
// Получаем строковое представление уникального идентификатора объекта
УИД_Объекта = Строка(Объект.Ссылка.УникальныйИдентификатор());
// Формируем ссылку с параметром "?ref="
НавСсылка = "e1cib/command/Справочник.Номенклатура.Команда.ОткрытьЦены?ref=" + УИД_Объекта;
ПерейтиПоНавигационнойСсылке(НавСсылка);
КонецЕсли;
КонецПроцедуры
Если вы разрабатываете функционал в современной типовой конфигурации 1С (такой как ERP, Управление торговлей, Комплексная автоматизация или Бухгалтерия предприятия), в которую интегрирована Библиотека Стандартных Подсистем (БСП), ручное программирование кнопок-оберток является не лучшей практикой.
В составе БСП есть мощная подсистема «Подключаемые команды». Она создана специально для того, чтобы автоматически собирать все доступные для конкретного объекта глобальные, общие и параметрические команды (печать, заполнение, отчеты, отправка) и динамически выводить их на форму в виде структурированных подменю.
Интеграция вашей глобальной команды через БСП включает в себя следующие шаги:
ПриОпределенииКомандПодключенныхКОбъекту).ПриСозданииНаСервере выполняете вызов инициализирующего метода БСП:
ПодключаемыеКоманды.ПриСозданииНаСервере(ЭтотОбъект);
&НаКлиенте
Процедура Подключаемый_ВыполнитьКоманду(Команда)
ПодключаемыеКомандыКлиент.ВыполнитьКоманду(ЭтотОбъект, Команда, Объект);
КонецПроцедуры
Использование БСП избавляет разработчика от необходимости жестко прописывать пути навигационных ссылок в кодовой базе модуля формы. Платформа совместно с библиотекой самостоятельно определяет актуальный состав прав пользователя на команду, видимость кнопок в зависимости от функциональных опций и корректно передает контекст текущего объекта при вызове выполнения.
Мы выяснили, что напрямую назначить общую или глобальную команду программно созданной кнопке невозможно из-за ограничений структуры метаданных управляемых форм 1С. Тем не менее, задача легко решается созданием локальной команды-посредника с последующим вызовом метода ПерейтиПоНавигационнойСсылке, либо делегированием этой задачи стандартным механизмам интеграции БСП, если разработка ведется в типовом решении.