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