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

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

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

Причина проблемы: клиентское кэширование представлений

Проанализируем архитектуру клиент-серверного взаимодействия в управляемом приложении. В отличие от толстого клиента, тонкий клиент оптимизирует сетевой трафик и количество серверных вызовов с помощью многоуровневого кэширования:

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

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

Способ 1. Использование метода ОтобразитьИзменениеДанных

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

Выясним синтаксис и особенности работы метода:

ОтобразитьИзменениеДанных(<Ссылка>, <ВидИзмененияДанных>);

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


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

В параметрах передается конкретная ссылка на измененный объект и значение системного перечисления ВидИзмененияДанных.Изменение. Этот вызов принудительно обновляет представление ссылки в тонком клиенте без лишней нагрузки на сервер.

Способ 2. Таргетированный вызов процедуры ОповеститьОбИзменении

Разберем работу стандартного механизма оповещения платформы. Метод ОповеститьОбИзменении() также доступен только на клиенте. Часто разработчики допускают ошибку, передавая тип объекта целиком, либо передавая тип родительского документа/справочника, а не самой ссылки из табличной части.

Если вызвать ОповеститьОбИзменении(Тип("СправочникСсылка.Проверки")), клиент сбросит кэш всех элементов данного справочника, что повлечет за собой избыточные сетевые запросы при дальнейшей навигации. Правильнее передавать точечные ссылки измененных объектов.

Посмотрим на пример обработки массива ссылок:


&НаКлиенте
Процедура ОбновитьКэшИзмененныхЭлементов(МассивИзмененныхСсылок)
    
    Для Каждого ТекСсылка Из МассивИзмененныхСсылок Цикл
        // Сбрасываем кэш конкретной ссылки справочника "Проверки"
        ОповеститьОбИзменении(ТекСсылка);
    КонецЦикла;
    
    ЭтаФорма.ОбновитьОтображениеДанных();
    
КонецПроцедуры

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

Способ 3. Использование отдельного текстового реквизита в табличной части

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

Разберем по шагам логику этого подхода:

  1. В колонке табличной части на форме отображаем не саму ссылку Проверка, а текстовый реквизит ПредставлениеПроверки.
  2. При получении данных из обработки на сервере формируем актуальное строковое наименование и напрямую записываем его в строку табличной части.
  3. Сама ссылка на справочник сохраняется в невидимой колонке для программной логики и проведения.

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


&НаСервере
Процедура ЗаполнитьСтрокиПоТаблице(ТаблицаИзХранилища)
    
    Объект.Проверки.Очистить();
    
    Для Каждого СтрДанных Из ТаблицаИзХранилища Цикл
        НоваяСтрока = Объект.Проверки.Добавить();
        НоваяСтрока.Проверка = СтрДанных.Ссылка;
        // Заполняем строковое представление напрямую, минуя кэш ссылок
        НоваяСтрока.ПредставлениеПроверки = СтрДанных.НовоеНаименование;
    КонецЦикла;
    
КонецПроцедуры

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

Важные ограничения и особенности

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

  1. Клиентский контекст: методы ОтобразитьИзменениеДанных() и ОповеститьОбИзменении() являются исключительно клиентскими процедурами. Их невозможно вызвать в общем модуле или модуле объекта на сервере. Если запись происходит на сервере, ссылки необходимо вернуть на клиент и вызвать методы там.
  2. Изоляция сеансов: вызовы методов сброса кэша работают только в рамках текущего клиентского сеанса. Пользователи в других сеансах увидят обновленное представление после перезапуска формы, повторного выбора элемента или по истечении времени жизни их локального кэша.
← На главную