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