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