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