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