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