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