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

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

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

Выясняем причину: почему стандартное обновление не работает

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

  1. Кэширование параметров запроса: Если в запросе ДС используются параметры (например, &ТекущийДокумент или &ЭтоНовый), метод Элементы.ИмяСписка.Обновить() просто перезапускает запрос с теми же значениями параметров, которые были установлены при открытии формы. Если ссылка документа изменилась (например, при записи нового объекта), список продолжит искать данные по старому значению.
  2. Сложная структура запроса: Наличие условий ГДЕ, конструкций ВЫБОР или соединений нескольких таблиц может сбивать платформу с толку — она не всегда может сопоставить измененную запись в базе с конкретной строкой в вашем списке.
  3. Отсутствие связи обработчика событий: Часто программный вызов Оповестить() не срабатывает просто потому, что процедура ОбработкаОповещения в модуле формы не назначена обработчиком события в палитре свойств формы.

Решение 1: Принудительное обновление параметров запроса

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


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

Проанализируем этот подход: явная установка параметра заставляет платформу пересмотреть кэш запроса и выполнить его с новыми вводными данными.

Решение 2: Синхронизация данных формы через метод Прочитать()

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


&НаСервере
Процедура ЗагрузитьДанныеНаСервере()
    // Вызов логики из модуля менеджера
    Документы.ТоварыSIM.ВыполнитьКомандуЗагрузки(Объект.Ссылка);
    
    // Читаем обновленный объект из базы в данные формы
    Прочитать(); 
КонецПроцедуры

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

Решение 3: Правильное использование механизма оповещений

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

  1. Откройте управляемую форму в конфигураторе.
  2. Перейдите в Свойства формы (правая кнопка мыши по корню дерева элементов — Свойства).
  3. Найдите событие ОбработкаОповещения и нажмите на лупу, чтобы создать или выбрать процедуру.
  4. Внутри процедуры обязательно используйте ОбновитьОтображениеДанных().

Пример корректной обработки:


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

Решение 4: Передача объекта «туда-обратно» (Context Switch)

Иногда лучшим способом является работа не со ссылкой, а с самим объектом формы. Это гарантирует, что форма будет «знать» обо всех изменениях. Рассмотрим способ передачи данных через преобразование в прикладной объект:


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

Решение 5: «Хак» с фиктивным параметром (Force Refresh)

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

В тексте запроса динамического списка добавим:

ГДЕ (1=1 ИЛИ &КлючОбновления = 0)

В коде обновления будем передавать туда случайное значение:


// Принудительный сброс кэша ДС
дсТоварыSIM.Параметры.УстановитьЗначениеПараметра("КлючОбновления", ТекущаяУниверсальнаяДатаВМиллисекундах());
Элементы.дсТоварыSIM.Обновить();

Поскольку значение параметра &КлючОбновления каждый раз новое, платформа 1С не может использовать закэшированный результат предыдущего запроса и выполняет полное обращение к базе данных. Это гарантирует 100% обновление данных в интерфейсе.

Резюме

Для надежного обновления динамического списка с произвольным запросом мы рекомендуем следующую последовательность действий: выполнение логики -> Прочитать() -> Установка параметров ДС -> Обновить(). Не забывайте проверять свойство ОсновнаяТаблица в настройках динамического списка — если оно заполнено, платформа гораздо лучше справляется с интерпретацией метода ОповеститьОбИзменении().

← На главную