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