При программном редактировании реквизитов элементов справочников (например, наименования) разработчики часто сталкиваются с ситуацией, когда данные в базе успешно изменяются, но в элементах интерфейса управляемой формы (деревьях значений, таблицах или полях ввода) старое представление ссылки продолжает отображаться без изменений. Выясним причину такого поведения платформы 1С:Предприятие и разберем практические способы принудительного обновления отображения данных.
Проанализируем, как клиентское приложение 1С работает со ссылочными данными. В целях оптимизации клиент-серверного взаимодействия и снижения нагрузки на сеть строковые представления ссылочных типов кэшируются на стороне тонкого или веб-клиента по уникальному идентификатору (UUID ссылки).
Когда мы программно модифицируем и записываем объект на сервере:
ИзменяемыйЭлемент = ТекущееЗначениеЭлемента.Ссылка.ПолучитьОбъект();
ЗаполнитьЗначенияСвойств(ИзменяемыйЭлемент, ТекущееЗначениеЭлемента);
ИзменяемыйЭлемент.Записать();
В самой базе данных наименование меняется сразу. Однако при повторном заполнении коллекции формы (например, дерева или таблицы значений) через ЗначениеВРеквизитФормы, клиент видит тот же самый идентификатор ссылки. Платформа считает, что строковое представление для данного объекта уже получено ранее, берет его из локального кэша и не отправляет повторный запрос на сервер. В результате в интерфейсе остается устаревшее значение.
Рассмотрим по шагам основные способы решения этой задачи в зависимости от используемой архитектуры формы.
Разберем стандартный механизм платформы для информирования всех элементов интерфейса об изменении ссылочного объекта. Метод ОповеститьОбИзменении принудительно сбрасывает закэшированное представление для переданной ссылки во всех открытых формах текущего сеанса.
Посмотрим, как организовать этот процесс при изменении данных:
ОповеститьОбИзменении(СсылкаНаОбъект).Пример реализации клиент-серверного взаимодействия:
&НаКлиенте
Процедура СохранитьИОбновить()
СсылкаНаОбъект = ЗаписатьЭлементНаСервере();
// Инвалидируем кэш представления для измененного элемента
ОповеститьОбИзменении(СсылкаНаОбъект);
// Перечитываем и обновляем дерево или таблицу на форме
ОбновитьДеревоНаСервере();
КонецПроцедуры
&НаСервере
Функция ЗаписатьЭлементНаСервере()
ОбъектСправочника = РеквизитФормыВЗначение("ТекущееЗначениеЭлемента");
ОбъектСправочника.Записать();
Возврат ОбъектСправочника.Ссылка;
КонецФункции
Если данные уже перезаполнены в реквизитах формы, но элементы управления не перерисовались с актуальными значениями, применим метод управляемой формы ОбновитьОтображениеДанных. Этот метод заставляет элементы формы заново перечитать отображаемые данные из связанных реквизитов.
&НаКлиенте
Процедура ПослеЗаписиДанных()
// Обновляем отображение всех элементов текущей формы
ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры
Рассмотрим наиболее надежный архитектурный подход для деревьев и таблиц значений на форме, который полностью исключает зависимость от клиентского кэша ссылок. Он заключается в явном получении строкового представления в запросе и выводе его в отдельную текстовую колонку.
Разберем алгоритм настройки:
СсылкаНаОбъект (тип СправочникСсылка..., колонка скрыта от пользователя) и НаименованиеОтображаемое (тип Строка, отображается в табличной части формы).ПРЕДСТАВЛЕНИЕ().Посмотрим на пример серверного кода:
&НаСервере
Процедура ЗаполнитьДеревоДанными()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Склады.Ссылка КАК Ссылка,
| Склады.Наименование КАК Наименование
|ИЗ
| Справочник.Склады КАК Склады";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
ДеревоОбъект = РеквизитФормыВЗначение("ДеревоНаФорме");
ДеревоОбъект.Строки.Очистить();
Пока Выборка.Следующий() Цикл
СтрокаДерева = ДеревоОбъект.Строки.Добавить();
СтрокаДерева.СсылкаНаОбъект = Выборка.Ссылка;
СтрокаДерева.НаименованиеОтображаемое = Выборка.Наименование;
КонецЦикла;
ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоНаФорме");
КонецПроцедуры
Так как колонка таблицы имеет тип Строка, клиент отображает значение напрямую из данных строки, не обращаясь к механизму кэширования представлений ссылок.
При передаче дерева значений через ЗначениеВРеквизитФормы полезно предварительно очистить строки реквизита формы. Это сигнализирует визуальным элементам о необходимости полной перерисовки структуры узлов:
&НаСервере
Процедура ПерезаполнитьДерево(ДеревоОбъект)
// Очищаем коллекцию на форме перед установкой новых значений
ДеревоНаФорме.ПолучитьЭлементы().Очистить();
ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоНаФорме");
КонецПроцедуры
Для гарантированного обновления строковых представлений рекомендуется сочетать вызов ОповеститьОбИзменении на клиенте с явным разделением ссылочных и строковых данных в сложных таблицах и деревьях значений.