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