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