Как переоткрыть форму обработки с нуля в 1С:Предприятие 8.3?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в 1С:Предприятие на управляемых формах часто возникает следующая задача: есть форма обработки (например, форма подбора номенклатуры), которая вызывается из документа. Если пользователь открывает эту же обработку из другого документа, платформа по умолчанию не создает новую форму, а просто активирует уже открытую. При этом код в обработчике ПриСозданииНаСервере повторно не выполняется, и форма остается со старыми параметрами.

Возникает закономерный вопрос: как заставить платформу закрыть текущий экземпляр и открыть совершенно новый, чтобы форма корректно инициализировалась согласно данным нового документа-владельца? Рассмотрим эту ситуацию подробнее и разберем по шагам правильные способы решения.

Почему нельзя просто использовать событие ПриПовторномОткрытии?

Первое, что приходит на ум разработчику — перехватить событие ПриПовторномОткрытии и обновить данные формы. Однако, проанализируем, почему этот подход считается неправильным с точки зрения архитектуры 1С:

  1. Ограничения стандартов разработки. В клиентских обработчиках ПриОткрытии и ПриПовторномОткрытии строго не рекомендуется выполнять серверные вызовы. Платформа проектировалась так, чтобы тяжелая инициализация интерфейса и данных происходила исключительно в процедуре ПриСозданииНаСервере. Нарушение этого правила приводит к неоптимальной работе и «тормозам» интерфейса.
  2. Жизненный цикл параметров. Свойство формы Параметры, через которое мы передаем данные из документа (например, ссылку на сам документ, вид цен, склад и т.д.), доступно в полном объеме только во время выполнения ПриСозданииНаСервере. Как только эта серверная процедура завершается, платформа очищает переданные параметры. Таким образом, в ПриПовторномОткрытии мы уже не сможем получить новые входные данные стандартным путем без написания «костылей».

Шаг 1: Гарантированное открытие новой формы с помощью Ключа Уникальности

Чтобы заставить платформу полностью пересоздать форму и заново пройти процедуру ПриСозданииНаСервере, мы должны обмануть механизм кэширования окон. Платформа идентифицирует открытые формы по специальному ключу уникальности. Если ключ совпадает — окно активируется, если нет — создается новое.

Посмотрим на пример того, как передать уникальный ключ при открытии формы. В функцию ОткрытьФорму четвертым параметром необходимо передать Новый УникальныйИдентификатор:


ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ДокументСсылка", Объект.Ссылка);
ПараметрыОткрытия.Вставить("Склад", Объект.Склад);

// Генерируем новый уникальный идентификатор для каждого открытия
КлючУникальности = Новый УникальныйИдентификатор;

// Открываем форму обработки с уникальным ключом
ОткрытьФорму("Обработка.ПодборНоменклатуры.Форма", ПараметрыОткрытия, ЭтаФорма, КлючУникальности);

Теперь при каждом вызове этого кода система будет открывать независимый экземпляр формы. Данные документа будут успешно переданы в параметры и обработаны на сервере.

Шаг 2: Программное закрытие старых окон

Использование уникального ключа решает проблему открытия с нуля, но порождает новую: если пользователь будет часто вызывать подбор, у него в фоне накопится множество открытых окон одной и той же обработки. Чтобы этого избежать, перед открытием новой формы старые необходимо закрыть.

Для этого в 1С предусмотрен глобальный метод ПолучитьОкна(), который возвращает массив всех открытых окон клиентского приложения (объекты типа ОкноКлиентскогоПриложения). Разберем, как можно найти и закрыть старую форму подбора перед открытием новой:


// 1. Получаем все открытые окна в приложении
МассивОкон = ПолучитьОкна();

// 2. Ищем нашу форму обработки среди открытых окон
Для Каждого ТекущееОкно Из МассивОкон Цикл
    
    // Получаем содержимое окна (саму форму)
    СодержимоеОкна = ТекущееОкно.ПолучитьСодержимое();
    
    Если СодержимоеОкна <> Неопределено Тогда
        // Проверяем по имени формы, что это именно наш подбор
        Если СодержимоеОкна.ИмяФормы = "Обработка.ПодборНоменклатуры.Форма.Форма" Тогда
            ТекущееОкно.Закрыть();
        КонецЕсли;
    КонецЕсли;
    
КонецЦикла;

// 3. Открываем новую форму (как в примере выше)
КлючУникальности = Новый УникальныйИдентификатор;
ОткрытьФорму("Обработка.ПодборНоменклатуры.Форма", ПараметрыОткрытия, ЭтаФорма, КлючУникальности);

Важные нюансы архитектуры и обработчики ожидания

Выясним еще одну важную деталь. Стандарты разработки 1С запрещают выполнять манипуляции с открытием и закрытием окон (переоткрытие) напрямую внутри обработчиков событий самой формы, таких как ПриОткрытии или ПриПовторномОткрытии. Если вы попытаетесь закрыть текущую форму и тут же открыть новую в синхронном потоке, это приведет к нарушению порядка отображения окон и сбою фокуса интерфейса.

Если логика вашей программы требует инициировать переоткрытие из самой же формы обработки, вам необходимо вынести этот процесс в асинхронный поток. Для этого отлично подходит метод ПодключитьОбработчикОжидания.

Рассмотрим пример, когда обработка сама решает, что ей нужно перезапуститься:


&НаКлиенте
Процедура ПриПовторномОткрытии(СтандартнаяОбработка)
    // Отменяем стандартное поведение
    СтандартнаяОбработка = Ложь;
    
    // Подключаем обработчик, который сработает через 0.1 секунду
    ПодключитьОбработчикОжидания("ПереоткрытьФормуАсинхронно", 0.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ПереоткрытьФормуАсинхронно()
    // Здесь размещаем код закрытия текущего окна и вызова ОткрытьФорму(...)
    ЭтаФорма.Закрыть();
    // Логика открытия с новым ключом уникальности...
КонецПроцедуры

Подводя итог, можно сказать, что правильное управление жизненным циклом управляемой формы заключается в комбинировании параметра КлючУникальности для генерации новых окон и обхода объектов ОкноКлиентскогоПриложения для подчистки неактуальных экземпляров. Такой подход гарантирует стабильную работу кэша и интерфейса в конфигурациях 1С.

← На главную