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

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

1С управляемые формы: как обновить форму программно

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

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

Управляемые формы в 1С работают по принципу разделения данных и представления: форма кэширует состояние и не следит за каждым изменением автоматически. Поэтому платформа предоставляет несколько штатных механизмов обновления — от универсального метода ОбновитьОтображениеДанных() до перечитывания объекта целиком через Прочитать() и обновления динамических списков.

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

Как работает обновление управляемой формы

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

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

ОбновитьОтображениеДанных(): базовый способ

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

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

&НаКлиенте

Процедура ПересчитатьИтоги(Команда)

ПересчитатьИтогиНаСервере();

ЭтаФорма.ОбновитьОтображениеДанных();

КонецПроцедуры

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

Прочитать(): когда данные изменились в базе

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

Метод доступен только для форм объектов (документов, справочников и т.п.) и вызывается на клиенте или на сервере:

&НаКлиенте

Процедура ОбновитьДанныеОбъекта(Команда)

ЭтаФорма.Прочитать();

КонецПроцедуры

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

&НаКлиенте

Процедура ОбновитьДанныеОбъекта(Команда)

Если ЭтаФорма.Модифицированность Тогда

ПоказатьПредупреждение(, "Сначала запишите объект: несохранённые изменения будут потеряны.");

Возврат;

КонецЕсли;

ЭтаФорма.Прочитать();

КонецПроцедуры

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

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

&НаКлиенте

Процедура ОбновитьСписок(Команда)

Элементы.СписокДокументов.Обновить();

КонецПроцедуры

Если данные меняются из вашего же кода — например, вы программно записали документы обработкой — дополнительно можно отправить оповещение об изменении, чтобы обновились все открытые формы, которые на него подписаны:

ОповеститьОбИзменении(ДокументСсылка);

// или для типа в целом:

ОповеститьОбИзменении(Тип("ДокументСсылка.РеализацияТоваровУслуг"));

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

Порядок обновления динамического списка
  1. 1
    Убедитесь, что данные реально записаны в базу (запись объекта завершена)
  2. 2
    Вызовите ОповеститьОбИзменении() для изменённых ссылок — обновятся подписанные формы
  3. 3
    Если список не обновился, вызовите Элементы.ИмяСписка.Обновить() на клиенте
  4. 4
    Проверьте, что у списка не заданы отбор или параметры, скрывающие новые записи

Обновление табличных частей и реквизитов формы

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

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

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ЗаписанПрикреплённыйФайл" Тогда

ЗаполнитьСписокФайлов();

ЭтаФорма.ОбновитьОтображениеДанных(Элементы.СписокФайлов);

КонецЕсли;

КонецПроцедуры

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

Сравнение способов обновления

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

Лёгкая синхронизация отображения с реквизитами формы. Не обращается к базе, не подходит при внешних изменениях данных

Прочитать()

Полное перечитывание объекта из базы. Подходит при внешних изменениях, но затирает несохранённые правки

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

Повторное выполнение запроса динамического списка. Только для списков, не влияет на форму объекта

ОповеститьОбИзменении()

Уведомляет все открытые формы об изменении ссылки или типа. Работает только в рамках текущего сеанса

Обновление формы из другой формы и по таймеру

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

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

&НаКлиенте

Процедура ПриОткрытии(Отказ)

ПодключитьОбработчикОжидания("ОбновитьСтатусы", 30);

КонецПроцедуры

&НаКлиенте

Процедура ОбновитьСтатусы()

ЗагрузитьСтатусыНаСервере();

ЭтаФорма.ОбновитьОтображениеДанных(Элементы.СтатусыОбмена);

КонецПроцедуры

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

Маршрут решения

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

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

Типичные ошибки и диагностика проблем

Самая частая жалоба — «данные изменились, а на форме старые значения». Причины почти всегда из короткого списка: изменения выполнены на сервере в отдельном вызове, но форма не обновлена; данные записаны в базу, но форма продолжает показывать свой снимок; динамический список не получил оповещения, потому что запись выполнялась программно без ОповеститьОбИзменении().

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

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

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

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

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

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

Значения в полях формы после обновления
Норма

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

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

Поля показывают данные до изменения

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

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

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

Строка появляется только после закрытия и открытия списка

Состояние модифицированности после Прочитать()
Норма

Пользователь предупреждён, данные не потеряны

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

Несохранённые правки исчезли без предупреждения

Производительность формы
Норма

Обновление вызывается один раз после пакета изменений

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

Обновление в цикле, форма подтормаживает

FAQ

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

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

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

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

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

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

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

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

Как автоматически обновлять форму каждые N секунд?

Используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", ИнтервалВСекундах) в обработчике ПриОткрытии. В вызываемой процедуре загружайте данные на сервере и обновляйте отображение. Не ставьте слишком маленький интервал и отключайте обработчик при закрытии формы.

ОбновитьОтображениеДанных() вызван, но данные на форме старые. Что не так?

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

Итог

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

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