Как в табличной части обновить отображение подчиненного реквизита?

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

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

Выясняем причину: Механизм кэширования объектов на клиенте

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

Этот кэш обладает следующими свойствами:

  1. Живучесть: Кэш может сохраняться в течение всего сеанса работы пользователя (процесс 1cv8.exe).
  2. Изоляция: Если изменение объекта произошло в другом сеансе или через фоновое задание, текущий сеанс «не узнает» об этом автоматически.
  3. Стойкость к переоткрытию: Часто даже закрытие и повторное открытие формы не очищает этот кэш, так как объект ссылки (например, СправочникСсылка.Номенклатура) уже «запомнил» свои связанные свойства для данного клиента.

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

Решение 1: Использование метода ОповеститьОбИзменении

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

Посмотрим на пример кода, который необходимо выполнить после того, как родитель номенклатуры был изменен на сервере:


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

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

Решение 2: Полное перечитывание данных формы

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


&НаСервере
Процедура ОбновитьДанныеОбъектаНаСервере()
    // Предположим, здесь была логика изменения данных в БД
    // ...
    
    // Перечитываем данные текущего объекта из БД
    ЭтаФорма.Прочитать(); 
КонецПроцедуры

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

Решение 3: Программное обновление через вспомогательный реквизит

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

  1. Добавляем в Данные табличной части формы (не в сам объект/документ, а именно в реквизиты формы) новую колонку, например, РодительНаименование (тип Строка).
  2. При открытии формы или при событии ПриИзменении номенклатуры программно заполняем эту колонку.
  3. Поскольку это прямой реквизит формы, он не кэшируется как ссылочное поле, и вы полностью контролируете его значение.

Пример заполнения такой колонки:


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

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

Чего делать не стоит: ОбновитьИнтерфейс и ОбновитьОтображениеДанных

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

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

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

← На главную