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

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

1С: как обновить реквизит формы

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

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

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

Ниже разобраны рабочие приёмы с примерами кода на встроенном языке, типичные ошибки и способы проверить, что обновление действительно сработало.

Как устроено отображение реквизитов на форме

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

Из этого следует главное правило: если вы присваиваете значение реквизиту формы, элемент управления, связанный с этим реквизитом, обновляется автоматически — платформа сама следит за связью «данные → отображение». Отдельная команда «перерисовать» обычно не нужна.

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

Простое присваивание значения реквизиту

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

&НаКлиенте

Процедура УстановитьСтатус(Команда)

ЭтаФорма.СтатусДокумента = "Согласован";

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

Если реквизит принадлежит основному объекту формы (например, реквизит документа), обращение идёт через реквизит «Объект»:

&НаСервере

Процедура ЗаполнитьКомментарийНаСервере()

Объект.Комментарий = "Сформировано автоматически";

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

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

Перечитывание объекта из базы методом Прочитать()

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

&НаСервере

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

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

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

Метод доступен только у форм, у которых есть основной реквизит объектного типа (справочник, документ, задача и т.п.). У произвольной формы без основного реквизита вызвать его нельзя — там придётся вручную получать данные запросом и заполнять реквизиты.

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

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

Динамический список (журнал документов, список справочника, произвольная выборка запросом) кэширует данные и не следит за изменениями в базе. Если после записи объекта или выполнения обработки список показывает устаревшие строки, его нужно обновить явно:

&НаКлиенте

Процедура ПослеЗаписиОбъекта()

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

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

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

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

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

Метод ОбновитьОтображениеДанных и когда он нужен

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

Реальные сценарии, где метод оправдан: вы изменили данные через объектную модель в обход реквизита формы, работаете с полем табличного документа или HTML-документа, либо столкнулись с редкой ситуацией рассинхронизации после массового программного заполнения таблицы значений.

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

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

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

&НаКлиенте

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

Если ИмяСобытия = "ИзмененКурсВалюты" Тогда

ЭтаФорма.ТекущийКурс = Параметр.Курс;

КонецЕсли;

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

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

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

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

Присваивание значения

Подходит, когда новое значение известно в коде формы. Самый быстрый способ, отображение обновляется автоматически

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

Когда объект изменён в базе вне формы. Затирает несохранённые изменения, требует основной реквизит объектного типа

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

Только для динамических списков. Перевыполняет запрос, сохраняет отбор и позицию

Оповестить / ОбработкаОповещения

Для синхронизации между разными формами без жёсткой связи между ними

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

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

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

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

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

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

Значение в поле ввода после присваивания
Норма

Поле сразу показывает новое значение

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

Поле пустое или старое — проверьте ПутьКДанным элемента

Список после записи объекта
Норма

Строка списка отображает актуальные данные без переоткрытия

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

Данные старые — добавьте ОповеститьОбИзменении или Обновить()

Поведение при несохранённых изменениях
Норма

Перед Прочитать() запрашивается подтверждение

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

Изменения исчезают молча — добавьте проверку Модифицированность

Часто задаваемые вопросы

Можно ли обновить реквизит формы без серверного вызова?

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

Почему Прочитать() выдаёт ошибку на моей форме?

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

Как обновить только одну строку динамического списка?

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

Поле на форме не обновляется, хотя реквизит меняется. Что проверить?

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

Нужно ли обновлять форму после Записать()?

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

Итог

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

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