К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно обновить форму в 1С

Как программно обновить форму в 1С: ОбновитьОтображениеДанных, Прочитать, оповещения между формами. Примеры кода, типичные ошибки и проверка результата.

Программное обновление формы — одна из самых частых задач при доработке конфигураций 1С:Предприятие. После изменения данных в фоновой процедуре, записи объекта из другой формы или выполнения обмена данными пользователь видит устаревшие значения, пока форма не будет перерисована. Разработчику нужно явно указать платформе, что содержимое формы устарело и его требуется перечитать или перерисовать.

В управляемых формах нет единственной команды «обновить всё»: существует несколько методов с разным назначением — от простого обновления отображения реквизитов до полного перечитывания объекта из базы данных. Выбор неправильного метода приводит либо к потере введённых пользователем данных, либо к тому, что форма визуально не меняется.

Ниже разобраны основные способы программного обновления формы, примеры кода для управляемых и обычных форм, механизм оповещений между окнами и типичные ошибки, из-за которых обновление «не срабатывает».

Какие методы обновления формы существуют

Платформа 1С предлагает несколько уровней «обновления», и важно понимать разницу между ними. Перерисовка интерфейса, перечитывание данных объекта и обновление динамического списка — три разные операции, которые часто путают.

Основные методы управляемой формы:

  • ОбновитьОтображениеДанных() — обновляет отображение элементов формы на основании текущих данных в памяти, не обращаясь к базе;
  • Прочитать() — перечитывает основной реквизит формы (объект) из базы данных, заменяя данные формы;
  • Элементы.Список.Обновить() — обновляет динамический список, выполняя его запрос заново;
  • Оповестить() / ОповеститьОбИзменении() — уведомляет другие открытые формы о необходимости обновиться.

Сравнение методов

ОбновитьОтображениеДанных

Подходит, когда данные в реквизитах формы уже изменены программно и нужно только перерисовать элементы. Не читает базу.

Прочитать

Нужен, когда объект изменён в базе другим сеансом или кодом. Внимание: несохранённые изменения пользователя будут потеряны.

Элементы.Список.Обновить

Только для динамических списков — форм списков документов и справочников.

Оповестить

Когда изменения произошли в одной форме, а обновить нужно другую, уже открытую.

Обновление отображения без перечитывания данных

Метод ОбновитьОтображениеДанных() — самый безопасный способ. Он применяется, когда вы программно изменили значения реквизитов формы (например, рассчитали итоги в серверной процедуре) и хотите, чтобы пользователь увидел актуальные значения.

bsl
&НаКлиенте
Процедура ПересчитатьИтоги(Команда)
	ПересчитатьИтогиНаСервере();
	ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры

&НаСервере
Процедура ПересчитатьИтогиНаСервере()
	Объект.СуммаДокумента = Объект.Товары.Итог("Сумма");
КонецПроцедуры

У метода есть необязательный параметр — конкретный элемент формы, который нужно обновить. Если передать, например, Элементы.Товары, перерисуется только табличная часть, что немного быстрее при больших формах.

Важно: если данные изменились не в реквизитах формы, а в самой базе данных (другой пользователь провёл документ), ОбновитьОтображениеДанных() ничего не покажет — он работает только с тем, что уже находится в памяти формы.

Перечитывание объекта из базы данных

Когда объект изменён вне текущей формы — фоновым заданием, другим пользователем, обменом данными — требуется полное перечитывание. В управляемой форме объекта (документа, элемента справочника) для этого служит метод Прочитать() самой формы.

bsl
&НаКлиенте
Процедура ОбновитьИзБазы(Команда)
	Если ЭтаФорма.Модифицированность Тогда
		ПоказатьПредупреждение(, "Сначала запишите изменения — перечитывание очистит несохранённые данные.");
		Возврат;
	КонецЕсли;
	ЭтаФорма.Прочитать();
КонецПроцедуры

Метод Прочитать() вызывает стандартные обработчики ПриЧтенииНаСервере и ПриСозданииНаСервере, поэтому вся логика инициализации формы отработает повторно. Это нужно учитывать: если в ПриСозданииНаСервере есть код, рассчитанный на однократное выполнение, добавляйте проверки.

Обновление динамического списка

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

bsl
&НаКлиенте
Процедура ОбновитьСписок(Команда)
	Элементы.Список.Обновить();
КонецПроцедуры

Динамические списки в типовых конфигурациях часто обновляются автоматически при записи объектов — платформа сама отслеживает изменения затронутых таблиц. Автообновление можно настроить или отключить в свойствах динамического списка. Если список «не видит» новые записи, проверьте, не отключено ли автоматическое обновление и не используется ли произвольный запрос с временными таблицами — в таких случаях автообновление может не срабатывать.

Для списков с произвольным запросом иногда надёжнее вызвать обновление через оповещение: после записи объекта выполнить ОповеститьОбИзменении(ТипЗнч), и платформа сама обновит все открытые списки соответствующего типа.

Оповещения между формами

Классический сценарий: из формы документа открывается дополнительная форма, пользователь в ней что-то меняет, и после закрытия основная форма должна отразить результат. Для этого предназначен механизм оповещений.

bsl
// В форме-источнике после изменения данных:
Оповестить("ИзмененыДанныеКонтрагента", КонтрагентСсылка, ЭтаФорма);

// В форме-приёмнике:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
	Если ИмяСобытия = "ИзмененыДанныеКонтрагента" Тогда
		ЭтаФорма.Прочитать();
	КонецЕсли;
КонецПроцедуры

Имя события — произвольная строка, договоритесь о едином соглашении по именованию внутри проекта. Параметр передаёт полезную нагрузку (ссылку, структуру), а источник позволяет отфильтровать оповещения, чтобы форма не реагировала на собственные уведомления.

Для стандартного случая «записали объект — обновить списки» есть более короткий путь: метод ОповеститьОбИзменении(Ссылка) или глобальный вызов ОповеститьОбИзменении(Тип). Все открытые формы списков этого типа обновятся автоматически, без написания обработчика.

Настройка оповещения между формами
  1. 1
    В форме-источнике после изменения данных вызовите Оповестить с уникальным именем события и параметром
  2. 2
    В форме-приёмнике создайте обработчик ОбработкаОповещения
  3. 3
    Внутри обработчика проверьте ИмяСобытия и при совпадении вызовите Прочитать() или ОбновитьОтображениеДанных()
  4. 4
    Проверьте сценарий: откройте обе формы, измените данные в источнике, убедитесь, что приёмник обновился

Обновление формы в обычном приложении

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

Также в обычных формах актуален метод ОбновитьДанныеФормы не существует — там обновление элементов управления, связанных с данными, происходит через механизм связей, а принудительная перерисовка выполняется именно через ЭтаФорма.Обновить(). При работе с унаследованными конфигурациями проверяйте, какой режим использует форма: код управляемой формы в обычной не скомпилируется и наоборот.

Типичные ошибки и как проверить результат

Большинство жалоб «обновление не работает» сводится к нескольким повторяющимся причинам. Разберите их до того, как искать ошибку в платформе.

Типичные ошибки
01
Вызов ОбновитьОтображениеДанных вместо Прочитать — данные в базе изменились, но форма показывает кэш из памяти
02
Прочитать без проверки Модифицированность — несохранённые вводы пользователя исчезают без предупреждения
03
Оповестить вызывается до записи объекта — приёмник перечитывает ещё старую версию из базы
04
Опечатка в имени события оповещения — обработчик ОбработкаОповещения никогда не срабатывает, ошибок при этом не возникает
05
Попытка обновить динамический список через ОбновитьОтображениеДанных вместо Элементы.Список.Обновить

Проверять результат удобно по контрольным точкам: видимое значение на форме, состояние модифицированности, срабатывание обработчиков. Ниже — признаки нормы и проблемы.

Контрольные точки

Как проверить результат

Значение реквизита на форме после обновления
Норма

Отображается актуальное значение из базы или расчёта

Тревожный признак

Показывается старое значение — значит, вызван не тот метод

Флаг Модифицированность после Прочитать
Норма

Сброшен, форма считается сохранённой

Тревожный признак

Остался установленным — возможно, код после чтения снова меняет данные

Срабатывание ОбработкаОповещения
Норма

Точка останова в обработчике срабатывает при событии

Тревожный признак

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

Динамический список после записи
Норма

Новая или изменённая строка видна без закрытия формы

Тревожный признак

Запись появляется только после переоткрытия — обновление списка не вызывается

Если обновление работает «через раз», проверяйте контекст выполнения: серверная процедура не имеет доступа к элементам формы напрямую, а клиентский вызов Прочитать() сам передаёт управление на сервер. Ошибки вида «метод недоступен в данном контексте» — признак того, что код размещён не в том директиве компиляции.

Итог

Что важно запомнить

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

Частые вопросы

Чем ОбновитьОтображениеДанных отличается от Прочитать?

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

Почему динамический список не обновляется после записи документа?

Чаще всего отключено автоматическое обновление в настройках динамического списка или используется произвольный запрос, по которому платформа не может отследить изменения. Решение — вызвать Элементы.Список.Обновить() вручную или использовать ОповеститьОбИзменении с типом объекта после записи.

Как обновить форму из фонового задания?

Фоновое задание не имеет доступа к интерфейсу. Нужно передать результат из задания через ДлительныеОперации или механизм оповещений: после завершения задания на клиенте вызвать Прочитать() или ОбновитьОтображениеДанных(). Прямой вызов методов формы из фонового сеанса невозможен.

Можно ли обновить только один элемент формы, а не всю форму?

Да. Метод ОбновитьОтображениеДанных принимает параметр — конкретный элемент формы, например ЭтаФорма.ОбновитьОтображениеДанных(Элементы.Товары). Это полезно для больших форм, где полная перерисовка ощутима по времени.

Почему после Прочитать пропали введённые пользователем данные?

Потому что Прочитать заменяет данные формы версией из базы, а несохранённые изменения существуют только в памяти. Перед вызовом проверяйте ЭтаФорма.Модифицированность и либо записывайте объект, либо запрашивайте у пользователя подтверждение на потерю изменений.

Как уведомить сразу все открытые формы об изменении объекта?

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