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