Разработка и Конфигурация · 10 мин
Как обратиться к открытой форме 1С
Как обратиться к открытой форме 1С из модуля: поиск среди открытых окон, ОткрытьФорму, ПолучитьФорму, оповещения. Примеры кода и типичные ошибки разработчиков.
Задача обратиться к уже открытой форме возникает, когда нужно обновить данные в открытом списке, передать значение из одной формы в другую или проверить, не открыт ли уже нужный объект. В управляемом приложении 1С нельзя просто «найти» форму по имени переменной — платформа изолирует формы друг от друга, и взаимодействие строится через параметры, оповещения и уникальность открытия.
Основные инструменты — методы ОткрытьФорму() и ПолучитьФорму(), глобальный контекст Оповестить() с обработчиком ОбработкаОповещения(), а также коллекция открытых окон ПолучитьОкна(). Выбор способа зависит от того, нужно ли открыть форму, если её нет, или только найти уже существующую.
Ниже разобраны рабочие сценарии с примерами кода, ограничения каждого подхода и типичные ошибки, из-за которых форма «не находится» или открывается повторно.
Как устроено взаимодействие форм в управляемом приложении
В управляемом приложении каждая форма работает в собственном контексте, и прямого доступа к переменным чужой формы нет. Нельзя написать что-то вроде ФормаСписка.Обновить(), просто зная имя формы — сначала нужно получить на неё ссылку.
Платформа предоставляет три механизма взаимодействия: открытие формы с уникальностью (позволяет получить ссылку на существующий экземпляр), оповещения (асинхронная передача сообщений между формами) и описание оповещения о закрытии (обратный вызов после закрытия модальной формы). Каждый механизм решает свою задачу, и смешивать их без необходимости не стоит.
Обращение к открытой форме через ОткрытьФорму с уникальностью
Самый практичный способ — вызвать ОткрытьФорму() с параметром уникальности. Если форма с таким ключом уже открыта, платформа не создаст дубликат, а вернёт ссылку на существующий экземпляр и активизирует его окно.
ФормаСписка = ОткрытьФорму("Справочник.Номенклатура.ФормаСписка", ,
, "МойКлючУникальности");
Если ФормаСписка <> Неопределено Тогда
ФормаСписка.ОбновитьОтображениеДанных();
КонецЕсли;
В качестве уникальности можно передавать строку, ссылку на объект или любой сериализуемый ключ. Для форм объектов уникальность по умолчанию — ссылка на объект: две формы одного элемента справочника не откроются одновременно, повторный вызов вернёт уже открытую.
Важно понимать: если форма с таким ключом не была открыта, метод создаст новую. Поэтому этот способ подходит, когда логика «открыть или получить существующую» допустима. Если открывать форму нельзя, используйте поиск через окна или оповещения.
Передача данных в открытую форму через Оповестить
Когда нужно сообщить всем открытым формам о событии — например, что записан новый элемент и списки надо обновить — используется метод Оповестить(). Он отправляет сообщение, которое получают все формы, у которых есть обработчик ОбработкаОповещения с подходящим именем события.
// В форме-источнике:
Оповестить("ЗаписанаНоменклатура", Новый Структура("Ссылка", СсылкаНаЭлемент), ЭтотОбъект);
// В форме-приёмнике:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ЗаписанаНоменклатура" Тогда
Элементы.Список.Обновить();
КонецЕсли;
КонецПроцедуры
Параметр Источник позволяет форме-приёмнику отфильтровать собственные сообщения и не реагировать на оповещения, отправленные ей самой. Имя события — произвольная строка, но в типовых конфигурациях принято использовать префиксы, например "Запись_" с именем объекта.
Это предпочтительный способ, когда форм-приёмников может быть несколько или вы не знаете, открыта ли форма вообще: отсутствие подписчиков не вызывает ошибку.
Поиск открытой формы через ПолучитьОкна
Если нужно проверить, открыта ли форма, не открывая её и не активизируя, используется метод ПолучитьОкна(). Он возвращает коллекцию окон клиентского приложения, у каждого окна есть содержимое — массив форм.
Окна = ПолучитьОкна();
Для Каждого Окно Из Окна Цикл
Для Каждого Форма Из Окно.Содержимое Цикл
Если ТипЗнч(Форма) = Тип("ФормаКлиентскогоПриложения")
И Форма.ИмяФормы = "Справочник.Номенклатура.Форма.ФормаЭлемента" Тогда
// форма найдена, можно обратиться к её свойствам
КонецЕсли;
КонецЦикла;
КонецЦикла;
У найденной формы доступны экспортные процедуры и функции, объявленные в её модуле с директивой &НаКлиенте, а также свойство ИмяФормы для идентификации. Обращение к реквизитам формы напрямую возможно, но считается хрупким решением — правильнее объявить в форме-приёмнике экспортный метод, например ПринятьДанные(Параметры).
- 1Получите коллекцию окон вызовом ПолучитьОкна()
- 2Переберите окна и их содержимое (Окно.Содержимое)
- 3Сравните Форма.ИмяФормы с полным именем нужной формы
- 4Проверьте тип — это должна быть ФормаКлиентскогоПриложения
- 5Вызовите экспортный метод найденной формы или прочитайте её свойства
Получение результата из формы через оповещение о закрытии
Обратная задача — форма открывается для выбора или ввода, а вызывающая сторона должна получить результат. Здесь используется параметр «Описание оповещения о закрытии» метода ОткрытьФорму() или ОткрытьФормуМодально().
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораЭлемента", ЭтотОбъект);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , ЭтотОбъект, , , ,
ОписаниеОповещения, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
&НаКлиенте
Процедура ПослеВыбораЭлемента(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
// обработка выбранного значения
КонецЕсли;
КонецПроцедуры
Открываемая форма возвращает результат вызовом Закрыть(ЗначениеРезультата). Если пользователь закрыл форму крестиком, в обработчик придёт Неопределено — этот случай обязательно нужно обрабатывать.
Сравнение способов обращения к открытой форме
| Способ | Когда применять | Ограничения |
|---|---|---|
| ОткрытьФорму с уникальностью | Нужно получить форму или открыть её, если нет | Активизирует окно, создаёт форму при отсутствии |
| Оповестить + ОбработкаОповещения | Уведомить одну или несколько форм о событии | Нет гарантии, что приёмник существует и отреагировал |
| ПолучитьОкна | Найти форму без открытия и активации | Требует перебора, хрупкая идентификация по ИмяФормы |
| ОписаниеОповещения при открытии | Получить результат из дочерней формы | Работает только при закрытии формы |
Как выбрать действие
Типичные ошибки и ограничения
Наиболее частая проблема — попытка обратиться к форме с сервера. Все перечисленные методы (ОткрытьФорму, Оповестить, ПолучитьОкна) доступны только на клиенте. Из серверной процедуры обратиться к открытой форме нельзя в принципе — сначала нужно вернуть управление в клиентский контекст.
Вторая ошибка — сравнение ИмяФормы с неполным именем. Свойство содержит полный путь вида "Справочник.Номенклатура.Форма.ФормаЭлемента", и сокращённое сравнение ничего не найдёт. Третья — ожидание, что Оповестить дойдёт до формы, открытой в другом сеансе: оповещения работают только внутри текущего сеанса пользователя.
Проверка результата и отладка
После внедрения механизма проверьте три сценария: форма-приёмник открыта (данные дошли), форма закрыта (ошибок нет), форм-приёмников несколько (все получили оповещение). Для отладки оповещений удобно временно добавить в ОбработкаОповещения вывод имени события через Сообщить() — так видно, какие события реально приходят в форму.
Признак корректной работы поиска через окна: найденная форма имеет ожидаемое ИмяФормы, а вызов её экспортного метода не вызывает исключения. Если перебор ничего не находит, убедитесь, что форма открыта в основном или вспомогательном окне именно текущего сеанса и что сравнение имени выполняется с учётом регистра и полного пути.
Что важно запомнить
Прямого доступа к чужой форме в управляемом приложении нет. Используйте ОткрытьФорму с уникальностью для получения существующей формы, Оповестить — для уведомления открытых форм, ПолучитьОкна — для поиска без активации, ОписаниеОповещения — для получения результата. Все методы работают только на клиенте и только внутри текущего сеанса.
Частые вопросы
Можно ли обратиться к открытой форме из серверной процедуры?
Нет. ОткрытьФорму, Оповестить и ПолучитьОкна доступны только в клиентском контексте. Нужные данные следует подготовить на сервере, вернуть их в клиентскую процедуру и уже там обратиться к форме.
Как понять, открыта ли форма, не открывая её заново?
Переберите коллекцию ПолучитьОкна() и содержимое каждого окна, сравнивая свойство ИмяФормы с полным именем нужной формы. Этот способ не активизирует окно и не создаёт новый экземпляр.
Почему Оповестить не доходит до формы-приёмника?
Проверьте три вещи: совпадает ли строка имени события посимвольно, есть ли у приёмника обработчик ОбработкаОповещения на клиенте, и не отфильтровывает ли приёмник событие по параметру Источник. Также помните, что оповещения не пересекают границу сеансов.
Чем ОткрытьФорму отличается от ПолучитьФорму?
ПолучитьФорму создаёт форму и возвращает ссылку, не показывая её пользователю; ОткрытьФорму сразу отображает форму. ПолучитьФорму применяют, когда нужно подготовить форму программно перед показом или получить её объект для обработки.
Можно ли вызвать процедуру найденной открытой формы?
Да, если процедура объявлена в модуле формы с ключевым словом Экспорт и директивой &НаКлиенте. Обращение к неэкспортным методам или серверным процедурам формы извне невозможно.
Что вернёт ОткрытьФорму, если форма с такой уникальностью уже открыта?
Вернётся ссылка на существующий экземпляр формы, её окно будет активизировано, новый экземпляр создан не будет. Это стандартный способ реализовать поведение «открыть или перейти к уже открытой».