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