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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Метод 1. Использование метода Обновить() для элемента формы

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

Рассмотрим пример кода, который вызывается после записи набора записей в регистр:


&НаКлиенте
Процедура ПослеЗаписиДанных(Команда)
    // Код записи в регистр на сервере...
    ЗаписатьДанныеВРегистрНаСервере();
    
    // Принудительное обновление списка
    Элементы.СписокРегистра.Обновить();
КонецПроцедуры

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

Метод 2. Оповещение системы через ОповеститьОбИзменении()

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

Выясним, как правильно использовать этот метод. Его необходимо вызывать на клиенте, передавая тип объекта или ссылку.


&НаКлиенте
Процедура СохранитьИОбновить()
    // Программная запись в регистр
    ЗаписатьНаборЗаписей();
    
    // Оповещаем систему об изменении типа ключа записи регистра
    ОповеститьОбИзменении(Тип("РегистрСведенийКлючЗаписи.ИмяВашегоРегистра"));
КонецПроцедуры

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

Метод 3. Программная манипуляция параметрами и отборами

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

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


&НаСервере
Процедура ОбновитьПараметрыСпискаНаСервере()
    // Переустановка параметра заставляет список пересчитать запрос
    Список.Параметры.УстановитьЗначениеПараметра("ТекущийДокумент", Объект.Ссылка);
КонецПроцедуры

&НаКлиенте
Процедура КомандаОбновить(Команда)
    ОбновитьПараметрыСпискаНаСервере();
    Элементы.Список.Обновить();
КонецПроцедуры

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

Метод 4. Использование механизма оповещений (Оповестить и ОбработкаОповещения)

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

Схема работы выглядит следующим образом:

  1. В форме, где происходит запись, вызываем Оповестить("ДанныеРегистраИзменены");.
  2. В форме со списком создаем обработчик события ОбработкаОповещения.

&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ДанныеРегистраИзменены" Тогда
        Элементы.Список.Обновить();
    КонецЕсли;
КонецПроцедуры

Этот метод хорош тем, что он не перегружает сервер лишними вызовами, а срабатывает только тогда, когда это действительно необходимо по логике приложения.

Почему список может не обновляться? Анализируем причины

Проанализируем неочевидные факторы, которые мешают обновлению данных, даже если код написан верно:

  1. Транзакционность. Если вы вызываете Обновить() или Оповестить() внутри транзакции записи (например, в процедуре ПриЗаписи на сервере), данные в базе еще не зафиксированы. Список попытается обновиться, прочитает старые данные из базы (так как новые еще не «видны» вне транзакции) и останется в прежнем состоянии. Вызывайте обновление только после завершения транзакции.
  2. Произвольный запрос без основной таблицы. Как упоминалось выше, если в свойствах списка не указана Основная таблица, платформа не может связать изменения в базе с этим конкретным элементом формы.
  3. Автообновление. В свойствах элемента формы «Таблица» (для динамического списка) есть флаг Автообновление и ПериодАвтообновления. Использование этого механизма позволяет списку обновляться самостоятельно каждые N секунд, однако это может создавать лишнюю нагрузку на сервер БД.
  4. Оптимизация видимости. Если список находится на неактивной вкладке Группы - Страницы, платформа может не обновлять его до тех пор, пока пользователь не перейдет на эту вкладку. Если вам критично иметь актуальные данные сразу, используйте событие ПриСменеСтраницы для вызова Обновить().

Итоговые рекомендации

Для достижения гарантированного результата мы рекомендуем комбинировать подходы:

Такой комплексный подход обеспечит корректное отображение данных и создаст у пользователя ощущение быстрой и отзывчивой системы.

← На главную