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

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

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

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

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

Когда мы программно модифицируем и записываем объект на сервере:


ИзменяемыйЭлемент = ТекущееЗначениеЭлемента.Ссылка.ПолучитьОбъект();
ЗаполнитьЗначенияСвойств(ИзменяемыйЭлемент, ТекущееЗначениеЭлемента);
ИзменяемыйЭлемент.Записать();

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

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

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

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

Посмотрим, как организовать этот процесс при изменении данных:

  1. На сервере выполняем запись объекта и возвращаем измененную ссылку на клиент.
  2. В клиентской процедуре вызываем платформенный метод ОповеститьОбИзменении(СсылкаНаОбъект).
  3. При необходимости обновляем саму коллекцию данных на форме.

Пример реализации клиент-серверного взаимодействия:


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

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

Способ 2. Принудительное обновление отображения данных формы

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


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

Способ 3. Разделение хранения ссылки и строкового представления в таблицах

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

Разберем алгоритм настройки:

  1. В реквизите формы (дереве или таблице значений) создаем две колонки: СсылкаНаОбъект (тип СправочникСсылка..., колонка скрыта от пользователя) и НаименованиеОтображаемое (тип Строка, отображается в табличной части формы).
  2. В запросе для заполнения таблицы явно выбираем наименование или используем функцию ПРЕДСТАВЛЕНИЕ().
  3. Заполняем обе колонки и передаем результат в реквизит формы.

Посмотрим на пример серверного кода:


&НаСервере
Процедура ЗаполнитьДеревоДанными()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Склады.Ссылка КАК Ссылка,
        |	Склады.Наименование КАК Наименование
        |ИЗ
        |	Справочник.Склады КАК Склады";
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    ДеревоОбъект = РеквизитФормыВЗначение("ДеревоНаФорме");
    ДеревоОбъект.Строки.Очистить();
    
    Пока Выборка.Следующий() Цикл
        СтрокаДерева = ДеревоОбъект.Строки.Добавить();
        СтрокаДерева.СсылкаНаОбъект = Выборка.Ссылка;
        СтрокаДерева.НаименованиеОтображаемое = Выборка.Наименование;
    КонецЦикла;
    
    ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоНаФорме");
КонецПроцедуры

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

Способ 4. Очистка реквизита перед загрузкой новых данных

При передаче дерева значений через ЗначениеВРеквизитФормы полезно предварительно очистить строки реквизита формы. Это сигнализирует визуальным элементам о необходимости полной перерисовки структуры узлов:


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

Сводные рекомендации

Для гарантированного обновления строковых представлений рекомендуется сочетать вызов ОповеститьОбИзменении на клиенте с явным разделением ссылочных и строковых данных в сложных таблицах и деревьях значений.

← На главную