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