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