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