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