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