Как программно обновить управляемую форму и актуализировать данные в 1С:Предприятие 8.3?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде «1С:Предприятие 8.3» (особенно при переходе на управляемый интерфейс) программисты часто сталкиваются с ситуацией, когда данные в базе данных или в серверном контексте обновились, но пользователь на экране видит устаревшую информацию. Форма визуально «зависает» со старыми значениями, а обновление происходит только после её закрытия и повторного открытия. Разберем детально, почему так происходит, и выясним эффективные способы программного обновления интерфейса и данных.

Почему данные на форме не обновляются автоматически?

Давайте проанализируем архитектуру управляемого приложения. В управляемом интерфейсе существует строгое разделение на клиентскую и серверную части. Данные формы (например, реквизит Объект) кэшируются на клиенте для обеспечения высокой скорости работы интерфейса. Когда мы программно изменяем объект на сервере (например, напрямую записываем документ в базу данных), клиентская форма «не знает» об этих изменениях. Ей требуется явное указание на необходимость синхронизации кэша с актуальным состоянием БД. Если этого не сделать, при попытке пользователя вручную записать документ возникнет критическая ошибка: «Данные были изменены или удалены другим пользователем».

Решение 1. Синхронизация данных через ЗначениеВРеквизитФормы

Рассмотрим самый распространенный сценарий: мы находимся в модуле управляемой формы документа или справочника, вносим изменения в объект на сервере и хотим, чтобы они мгновенно отобразились у пользователя на экране.

Для решения этой задачи в платформе предусмотрен специальный механизм взаимного преобразования данных формы в прикладные объекты базы данных и обратно. Выполним процедуру по шагам:

  1. Сначала конвертируем данные формы в прикладной объект базы данных с помощью функции РеквизитФормыВЗначение().
  2. Производим необходимые программные манипуляции с данными (например, заполняем реквизиты, очищаем или заполняем табличные части) и записываем объект.
  3. Возвращаем измененный объект обратно в контекст формы с помощью процедуры ЗначениеВРеквизитФормы(). Это мгновенно обновит отображение данных у пользователя.

Посмотрим на практический пример реализации этого алгоритма в серверной процедуре формы:


&НаСервере
Процедура ПрограммноИзменитьИОбновитьНаСервере()
    // Преобразуем данные формы в реальный объект для записи
    ДокументОбъект = РеквизитФормыВЗначение("Объект");
    
    // Вносим программные изменения в табличную часть "Товары"
    ДокументОбъект.Товары.Очистить();
    НоваяСтрока = ДокументОбъект.Товары.Добавить();
    НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("00000001");
    НоваяСтрока.Количество = 10;
    
    // Записываем измененный объект в базу данных
    ДокументОбъект.Записать();
    
    // Возвращаем обновленный объект обратно в реквизит управляемой формы
    ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры

Этот метод является наиболее безопасным и производительным стандартом разработки, так как он исключает возникновение конфликтов блокировок и ошибок при последующем сохранении формы пользователем.

Решение 2. Полное перечитывание данных из базы с помощью Прочитать()

Рассмотрим другую ситуацию: данные текущего объекта были изменены сторонним процессом (например, фоновым заданием, другой формой, внешней обработкой или другим пользователем), и нам требуется просто подтянуть актуальное состояние объекта из базы данных в уже открытую форму.

Для этой задачи идеально подходит метод управляемой формы Прочитать(). Давайте разберем пример его вызова:


&НаКлинете
Процедура ОбновитьДанныеИзБазы()
    // Метод перечитывает основной реквизит формы непосредственно из СУБД
    ЭтаФорма.Прочитать();
КонецПроцедуры

Важное предупреждение: метод Прочитать() полностью перезаписывает текущие данные формы актуальными данными из базы данных. Если пользователь успел ввести какие-то изменения руками на форме, но еще не нажал кнопку «Записать», эти изменения будут стерты без предупреждения. Используйте этот метод обдуманно.

Решение 3. Обновление интерфейса через ОбновитьОтображениеДанных()

Часто разработчики путают обновление самих данных с обновлением визуальных элементов. Метод ОбновитьОтображениеДанных() не обращается к базе данных и не считывает новые значения полей. Он предназначен исключительно для принудительного обновления отображения интерфейса на клиенте.

Когда это полезно? Например, когда на форме настроено условное оформление или видимость элементов, зависящая от локальных реквизитов формы. Если платформа «задерживает» перерисовку экрана, мы можем форсировать этот процесс:


&НаКлиенте
Процедура ПриИзмененииПараметровОформления()
    // Изменяем локальный реквизит формы, влияющий на видимость элементов
    ИспользоватьРасширенныйРежим = Истина;
    
    // Принудительно заставляем платформу применить правила условного оформления
    ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры

Отметим, что для обычных (неуправляемых) форм в старых конфигурациях на платформе 1С 8.2 / 8.3 для аналогичных целей использовался простой метод Обновить(), который в управляемом приложении не применяется к форме напрямую.

Решение 4. Программное обновление Динамических списков

Работа со списками документов или справочников на форме требует индивидуального подхода. Если данные в динамическом списке изменились (например, мы открыли форму документа, провели его, закрыли, а в списке статус не обновился), у нас есть два основных пути решения проблемы.

Вариант А: Использование метода Обновить() для элемента формы

Если мы находимся непосредственно внутри формы списка и хотим принудительно обновить именно эту таблицу, мы обращаемся к ее элементу на клиенте:


&НаКлиенте
Процедура ОбновитьТекущийСписок()
    // Принудительный перезапрос данных динамического списка из СУБД
    Элементы.Список.Обновить();
КонецПроцедуры

Этот метод хорош тем, что он сохраняет позиционирование курсора (активную строку) для пользователя, предотвращая раздражающие «прыжки» списка к началу.

Вариант Б: Глобальное оповещение через ОповеститьОбИзменении()

Если изменения произошли в одном месте программы (например, в форме редактирования документа), а обновить нужно все открытые динамические списки этого типа на других экранах, используется глобальный метод:


&НаКлиенте
Процедура ПослеЗаписиОбъекта()
    // Оповещаем систему об изменении конкретного документа
    ОповеститьОбИзменении(ЭтаФорма.Объект.Ссылка);
КонецПроцедуры

Важная деталь: метод ОповеститьОбИзменении() эффективно работает в автоматическом режиме только в том случае, если у динамического списка в его свойствах заполнено свойство «Основная таблица». Если ваш динамический список построен на сложном произвольном запросе (например, с объединением таблиц виртуальных регистров) без указания основной таблицы, платформа не сможет сопоставить измененную ссылку со списком, и автоматического обновления не произойдет.

В таких случаях рекомендуется использовать классическую связку методов Оповестить() в форме редактирования и обработчик ОбработкаОповещения в форме списка, где будет явно вызываться метод Элементы.ИмяСписка.Обновить().

Резюме по методам обновления

Для закрепления материала систематизируем правила выбора нужного инструмента:

← На главную