Как обновить данные в динамическом списке при изменении статуса документа

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

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

Использование свойства списка ПериодАвтоОбновления (например, с интервалом в 1 секунду) является крайне нежелательным приемом: постоянные фоновые запросы создают паразитную нагрузку на сервер 1С и СУБД. Разберем причины такого поведения платформы и подробно рассмотрим оптимальные способы корректного обновления данных в интерфейсе.

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

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

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

Способ 1. Использование механизма пользовательских оповещений

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

Разберем по шагам реализацию этой схемы.

Шаг 1. В модуле формы документа в процедуре обработчика команды, которая меняет статус и производит запись в регистр, вызываем клиентскую процедуру Оповестить():


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

Шаг 2. В модуле формы списка документов определяем обработчик события ОбработкаОповещения. При получении события с заданным именем выполняем обновление таблицы динамического списка:


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

Метод Элементы.Список.Обновить() инициирует серверное обращение и повторное выполнение запроса списка, в результате чего пользователь сразу видит актуальные записи регистра сведений.

Способ 2. Использование штатного метода ОповеститьОбИзменении

Рассмотрим более производительную альтернативу, встроенную в платформу 1С. Метод ОповеститьОбИзменении() информирует платформу об изменении объекта без необходимости прописывать код перехвата оповещения в форме списка.

Посмотрим на пример вызова в модуле формы документа:


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

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

Способ 3. Передача описания оповещения о закрытии

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

Разберем по шагам реализацию в форме списка:


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

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

В этом сценарии событие обновления вызывается непосредственно в момент возврата управления в форму списка после закрытия документа.

Способ 4. Синхронизация записи регистра с транзакцией документа

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

← На главную