В разработке на платформе 1С:Предприятие 8 часто возникают задачи, когда состав элементов управления на форме заранее неизвестен и должен зависеть от данных в базе (иногда требуется выгрузка обычных форм в xml/bsl для миграции старых наработок). Например, нам нужно вывести на форму столько кнопок, сколько элементов содержится в определенном справочнике или списке значений. Рассмотрим подробнее, как реализовать этот механизм на управляемых формах, соблюдая правильную архитектуру и методику платформы.
Прежде чем приступать к написанию кода, разберем важный нюанс: в управляемом приложении кнопка не существует сама по себе. Для того чтобы кнопка на форме работала, она должна быть связана с Командой формы. Команда определяет логику (что произойдет при нажатии), а Элемент (кнопка) отвечает за визуальное отображение на форме.
Процесс программного создания всегда состоит из двух этапов:
КомандаФормы в коллекции ЭтаФорма.Команды (также в типовых решениях часто применяются подключаемые команды БСП).КнопкаФормы в коллекции ЭтаФорма.Элементы и привязка её к созданной команде.Создание элементов формы должно происходить исключительно в серверном контексте, как правило, в процедуре ПриСозданииНаСервере (хотя существуют способы реализовать добавление элементов формы без кодирования). Проанализируем ситуацию, когда нам нужно создать кнопки на основании элементов справочника. Сначала мы получим данные, а затем в цикле создадим программные объекты.
Рассмотрим пример кода:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем данные из справочника (например, категории товаров)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Категории.Ссылка КАК Ссылка,
| Категории.Наименование КАК Наименование,
| Категории.Код КАК Код
|ИЗ
| Справочник.Категории КАК Категории";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// 1. Создаем уникальное имя для команды и кнопки
ИмяОбъекта = "ДинамическаяКнопка_" + СтрЗаменить(Выборка.Код, " ", "");
// 2. Добавляем команду формы
НоваяКоманда = ЭтаФорма.Команды.Добавить(ИмяОбъекта);
НоваяКоманда.Заголовок = Выборка.Наименование;
НоваяКоманда.Действие = "ОбработчикНажатияДинамическойКнопки"; // Имя клиентской процедуры
// 3. Добавляем кнопку на форму
НовыйЭлемент = ЭтаФорма.Элементы.Добавить(ИмяОбъекта, Тип("КнопкаФормы"), ЭтаФорма);
НовыйЭлемент.ИмяКоманды = ИмяОбъекта;
// Чтобы потом найти ссылку, можно сохранить её в свойстве кнопки (если нужно)
// Но лучше использовать имя кнопки для идентификации
КонецЦикла;
КонецПроцедуры
Если мы будем просто добавлять кнопки в ЭтаФорма, они выстроятся в один длинный вертикальный список. Для управления визуальным представлением также часто используется условное оформление формы — эта задача решается через расширение для динамического управления структурой форм. Чтобы кнопки располагались горизонтально или сеткой, выясним, как использовать группы формы. Создадим программно группу с видом ГруппаКнопок.
&НаСервере
Процедура СоздатьГруппуДляКнопок()
ГруппаКнопок = Элементы.Добавить("ГруппаДинамическихКнопок", Тип("ГруппаФормы"), ЭтаФорма);
ГруппаКнопок.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ГруппаКнопок.Группировка = ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяЕслиВозможно;
ГруппаКнопок.ОтображатьЗаголовок = Ложь;
// Теперь при создании кнопок в качестве родителя указываем эту группу:
// НовыйЭлемент = ЭтаФорма.Элементы.Добавить(ИмяОбъекта, Тип("КнопкаФормы"), ГруппаКнопок);
КонецПроцедуры
Создавать отдельную процедуру для каждой кнопки нецелесообразно, особенно если их 50. Проанализируем ситуацию: как в одной процедуре понять, какая именно кнопка была нажата? Для этого мы используем свойство ЭтаФорма.ТекущийЭлемент.
Напишем клиентский обработчик, который будет открывать ссылку на элемент справочника, соответствующий нажатой кнопке:
&НаКлиенте
Процедура ОбработчикНажатияДинамическойКнопки(Команда)
// Получаем имя нажатой кнопки через текущий элемент формы
ИмяНажатойКнопки = ЭтаФорма.ТекущийЭлемент.Имя;
// Вычленяем идентификатор (код), который мы заложили в имя при создании
КодЭлемента = СтрЗаменить(ИмяНажатойКнопки, "ДинамическаяКнопка_", "");
// Вызываем серверный метод для получения ссылки по коду и выполнения действий
СсылкаНаОбъект = ПолучитьСсылкуНаСервере(КодЭлемента);
Если Не СсылкаНаОбъект.Пустая() Тогда
ПоказатьЗначение(, СсылкаНаОбъект);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСсылкуНаСервере(Код)
Возврат Справочники.Категории.НайтиПоКоду(Код);
КонецФункции
При динамическом создании элементов интерфейса следует учитывать несколько критически важных моментов, чтобы форма не стала "неповоротливой" и не вызывала ошибок у пользователей:
"Кн_") и добавляйте уникальный идентификатор (GUID или Код).ТаблицыФормы (списка), стилизованного под кнопки, или динамического списка с режимом "Список".Элементы и Команды доступны только на сервере. На клиенте можно менять свойства (видимость, доступность), но не структуру формы.Таким образом, мы разобрали полный цикл программного управления интерфейсом. Сочетание серверного создания структуры и клиентской логики единого обработчика позволяет создавать гибкие и динамичные рабочие места в 1С — в этом поможет конструктор динамических интерфейсов и рабочих столов 1С.