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