Обновление формы и перерисовка данных в 1С 8.3
Содержание
Чтобы вручную обновить окно в 1С, нажмите F5 или команду Обновить в командной панели списка — динамический список перечитается с сервера. Программно окно обновляют иначе: динамический список — методом Элементы.Список.Обновить(), данные формы объекта — методом формы Прочитать(), а связанные формы оповещают друг друга через Оповестить() и обработчик ОбработкаОповещения.
Распространённое заблуждение — что есть одна «кнопка обновить всё». Её нет. «Обновить окно» в 1С 8.3 — это три разные задачи с разными методами, и перепутать их легко: перечитать данные из базы, обновить список строк и перерисовать внешний вид формы — не одно и то же. Разберём каждый механизм и события, которые за него отвечают, на управляемых формах платформы «Такси».
Что на самом деле значит «обновить окно»
За словом «обновить» в 1С прячутся три непохожие операции. Прежде чем писать код, определите, что именно устарело на экране.
- 🔄 Данные формы объекта. Кто-то изменил и записал документ или элемент справочника, а у вас открыта его форма со старыми реквизитами. Нужно перечитать объект из базы.
- 📋 Строки динамического списка. Открыт список документов, в базу добавилась новая строка, а список её не показывает. Нужно перечитать сам список.
- 🎨 Внешний вид формы. Данные верные, но не пересчиталось условное оформление, видимость или доступность элементов. Нужно перерисовать форму, не трогая базу.
Каждой задаче — свой метод. Если применить не тот, окно либо не обновится вовсе, либо обновится лишнее и форма начнёт «тормозить». Дальше — по порядку.
Перечитать данные открытой формы
Когда у формы есть основной объект (документ, элемент справочника) и его поменяли в базе, используйте метод формы Прочитать().
&НаКлиенте
Процедура ПеречитатьВыполнить(Команда)
Прочитать();
КонецПроцедуры
Метод перечитывает объект с сервера. Все несохранённые изменения на форме при этом теряются — платформа покажет предупреждение, если форма модифицирована. Поэтому Прочитать() уместен там, где пользователь осознанно хочет вернуться к сохранённой версии.
Если нужно только перерисовать форму — пересчитать условное оформление, обновить отображаемые данные, не читая объект заново, — вызывают метод формы ОбновитьОтображениеДанных().
&НаКлиенте
Процедура ПриИзмененииСтавки(Элемент)
ОбновитьОтображениеДанных();
КонецПроцедуры
Разница принципиальная. Прочитать() идёт в базу и затирает правки. ОбновитьОтображениеДанных() работает с тем, что уже на форме: пересчитывает оформление и перерисовывает элементы, но не обращается к записанному объекту. Для динамического списка не подходит ни то, ни другое — у него свой метод.
Как обновить динамический список в окне
Список строк в окне (журнал документов
, список справочника, таблица на форме, подключённая к динамическому списку) перечитывают методом Обновить() у элемента формы.
&НаКлиенте
Процедура ОбновитьСписок(Команда)
Элементы.Список.Обновить();
КонецПроцедуры
Список здесь — имя элемента формы, а не имя реквизита. Если список называется иначе, подставьте фактическое имя из дерева элементов формы.
Вручную то же самое делает стандартная команда Обновить (горячая клавиша F5), которая есть у любой формы списка. Нажатие перечитывает список с актуальными данными базы.
Важно не путать два окна. Клавиша F5 обновляет список, но не перечитывает форму открытого объекта — если вы стоите в карточке документа, F5 в ней на реквизиты не повлияет. Для формы объекта обновление делают методом Прочитать() из предыдущего раздела.
У элемента формы с динамическим списком в палитре свойств есть период автоматического обновления (задаётся в секундах). Если его заполнить, список сам перечитывается с заданным интервалом без участия пользователя — удобно для оперативных журналов, где данные меняют несколько человек. Про обратную сторону такого автообновления — в разделе о производительности.
Оповестить и ОбработкаОповещения: сигнал между формами
Самый частый сценарий: пользователь из формы документа создал и записал новый элемент справочника, а список контрагентов в соседнем окне про это не знает. Открытые формы не следят друг за другом автоматически — им нужно послать сигнал. Для этого служит пара Оповестить() и ОбработкаОповещения.
Форма-источник после записи шлёт оповещение. Удобное место — обработчик ПослеЗаписи:
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
Оповестить("ЗаписанКонтрагент", Объект.Ссылка);
КонецПроцедуры
Форма-приёмник ловит сигнал в обработчике ОбработкаОповещения и решает, что делать:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ЗаписанКонтрагент" Тогда
Элементы.СписокКонтрагентов.Обновить();
КонецЕсли;
КонецПроцедуры
Три детали, на которых держится вся схема:
- Оба метода — клиентские.
Оповестить()иОбработкаОповещенияработают только на клиенте. ВызовОповестить()из серверной процедуры ничего не сделает. - Имя события — обычная строка. Один и тот же текст должен стоять и в вызове
Оповестить(), и в условии обработчика. Опечатка — и сигнал уходит в пустоту. - Параметр произвольный. Через второй аргумент передают ссылку, структуру, что угодно — приёмник сам решает, нужно ли реагировать именно на этот объект.
Оповестить() рассылает сигнал всем открытым формам сеанса. Поэтому проверяйте ИмяСобытия, а при необходимости и Источник — иначе на одно событие отреагируют формы, которых оно не касается.
ОповеститьОбИзменении: автообновление связанных списков
Писать Оповестить/ОбработкаОповещения под каждую связку форм вручную — долго. Для типового случая «объект записан — обновите списки, где он виден» в платформе есть готовый механизм ОповеститьОбИзменении().
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
ОповеститьОбИзменении(Объект.Ссылка);
КонецПроцедуры
Метод сообщает платформе, что объект указанного типа изменился. Динамические списки, которые показывают объекты этого типа и у которых не отключено обновление по изменению, перечитают свои данные сами. Ручной обработчик ОбработкаОповещения для этого писать не нужно.
Разница с Оповестить() простая:
ОповеститьОбИзменении()— про данные: «объект такого-то типа изменился, обновите связанные списки». Реагирует платформа.Оповестить()— про логику: «произошло вот такое событие», а что с ним делать, решает ваш код вОбработкаОповещения.
В типовых конфигурациях (БП 3.0, ЗУП 3.1, УТ 11) стандартные формы уже вызывают ОповеститьОбИзменении при записи, поэтому списки обновляются «сами собой». Дописывать его приходится в собственных обработках и доработках.
В отличие от Оповестить(), метод ОповеститьОбИзменении() доступен и на клиенте, и на сервере. Поэтому его удобно вызывать в ПослеЗаписиНаСервере, рядом с кодом записи объекта, не перенося логику в клиентский контекст.
Обновление окна по таймеру
Иногда окно нужно обновлять периодически, без действий пользователя: монитор заявок, панель оперативных остатков. Два штатных способа.
Автообновление динамического списка. Если в окне главное — список, достаточно задать период обновления в свойствах элемента (см. выше). Код не нужен.
Обработчик ожидания. Когда обновлять надо по своей логике, подключите клиентский обработчик ожидания:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ОбновитьПоТаймеру", 60);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьПоТаймеру()
Элементы.Список.Обновить();
КонецПроцедуры
ПодключитьОбработчикОжидания(ИмяПроцедуры, Интервал) вызывает процедуру каждые Интервал секунд (минимум — 1 секунда). Когда периодическое обновление больше не нужно, отключайте его методом ОтключитьОбработчикОжидания("ОбновитьПоТаймеру"), иначе таймер продолжит работать и нагружать сервер даже после того, как пользователь перестал смотреть на окно.
Обработчик ожидания работает во всех клиентах — толстом, тонком и веб. Процедуру-обработчик пишут без параметров: платформа вызывает её сама, передавать в неё ничего не нужно.
Какой метод выбрать: сводная таблица
| Что нужно обновить | Метод | Где вызывать |
|---|---|---|
| Строки динамического списка | Элементы.Список.Обновить() | клиент |
| Данные объекта формы из базы | Прочитать() (теряет правки) | клиент |
| Внешний вид, условное оформление | ОбновитьОтображениеДанных() | клиент |
| Обновить другую открытую форму | Оповестить() + ОбработкаОповещения | клиент |
| Обновить списки по факту записи | ОповеститьОбИзменении() | клиент/сервер |
| Периодически по таймеру | ПодключитьОбработчикОжидания() | клиент |
| Вручную пользователем | команда Обновить / F5 | — |
Общее правило: обновляйте точечно. Если изменился один список — обновите один список, а не всю форму.
Производительность и частые ошибки
Обновление окна — это запросы к серверу и СУБД. Лишние вызовы напрямую бьют по скорости.
- ⚠️ Короткий период автообновления. Период в 1–5 секунд на списке, который видят десятки пользователей, создаёт поток однотипных запросов к базе. Для оперативных журналов ставьте 30–60 секунд и больше — секундная свежесть почти никогда не нужна.
- ⚠️
ОбновитьОтображениеДанных()на тяжёлой форме. Метод пересчитывает всё условное оформление. На форме с большим табличным полем и множеством правил оформления частый вызов заметно подтормаживает. Вызывайте его по факту изменения, а не в каждом обработчике. - ⚠️ Полное перечитывание вместо точечного.
Прочитать()ради обновления одного реквизита — перебор: он идёт за всем объектом и теряет несохранённые правки. Чаще достаточно обновить список или перерисовать форму.
Типичные ошибки, из-за которых окно «не обновляется»:
Оповестить()вызвали на сервере. Метод клиентский. В серверной процедуре он не сработает — выносите вызов в клиентский контекст.- Не совпали имена события. В
Оповестить()одно написание, вОбработкаОповещения— другое. Сигнал уходит, но условие не срабатывает. - Нет обработчика
ОбработкаОповещения. Оповещение рассылается, но принимающая форма его не слушает — реакции ноль. - Путают методы.
ОбновитьОтображениеДанных()не читает объект из базы заново, аПрочитать()не перечитывает динамический список. Для списка — толькоОбновить(). - Рекурсия в обработчике. Если
ОбработкаОповещениясама вызываетОповестить()с тем же именем события, формы будут бесконечно будить друг друга.
Чем `Оповестить` отличается от `ОповеститьОбИзменении`?
ОповеститьОбИзменении — про данные: сообщает платформе, что объект изменился, и связанные динамические списки обновляются сами. Оповестить — про событие: шлёт сигнал с произвольным именем, а реакцию вы пишете вручную в ОбработкаОповещения.Почему не срабатывает `ОбработкаОповещения`?
Оповестить() вызван на сервере (метод клиентский), имя события в вызове и в обработчике написаны по-разному, либо на форме вообще нет процедуры ОбработкаОповещения.Как обновить список после записи элемента из другой формы?
Оповестить("ИмяСобытия", Объект.Ссылка), а в форме со списком в ОбработкаОповещения поймайте это событие и вызовите Элементы.Список.Обновить(). Либо используйте ОповеститьОбИзменении(Объект.Ссылка) — тогда ручной обработчик не нужен.Можно ли обновлять окно автоматически по времени?
ПодключитьОбработчикОжидания с интервалом в секундах.Как пользователю обновить окно вручную?
F5 или команду Обновить в командной панели списка — она перечитает динамический список с актуальными данными.