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