Как обновить содержимое одной управляемой формы при изменении данных в другой?

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

В разработке на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда пользователь работает одновременно с несколькими открытыми окнами. Например, в одной форме редактируется запись регистра или документ, а в другой открыт список этих записей или отчет. Нам необходимо, чтобы при нажатии кнопки «Записать» или выполнении любого другого действия в первой форме, данные во второй форме обновились автоматически, без необходимости ручного нажатия кнопки «Обновить». Разберем, как реализовать это максимально эффективно.

Механизм «Оповестить» и «ОбработкаОповещения»

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

Метод Оповестить вызывается на клиенте и «рассылает» сообщение всем активным формам. У этого метода есть три параметра: ИмяСобытия, Параметр и Источник. Проанализируем, как это реализовать в коде.

В форме-источнике (где данные меняются) мы вызываем оповещение:


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

В форме-приемнике (которую нужно обновить) необходимо создать обработчик события ОбработкаОповещения. Рассмотрим пример реализации:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    // Проверяем, то ли это событие, которое мы ждем
    Если ИмяСобытия = "ОбновитьДанныеКонтрагента" Тогда
        // Проанализируем параметры, если нужно обновить конкретную строку
        Если Параметр.Ссылка = Объект.Ссылка Тогда
            // Если это форма объекта - перечитываем данные с сервера
            ЭтаФорма.Прочитать(); 
        Иначе
            // Если это форма списка - обновляем отображение элементов
            Элементы.Список.Обновить();
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важный нюанс: метод ОбработкаОповещения срабатывает только в тех формах, которые открыты в данный момент. Если форма закрыта, она не получит оповещение, но это и не требуется, так как при следующем открытии она в любом случае прочитает актуальные данные из базы.

Использование метода «ОповеститьОбИзменении»

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

Рассмотрим, как правильно указать тип для регистра сведений, так как именно здесь программисты чаще всего совершают ошибки. Выясним причину: регистр сведений не имеет ссылки, поэтому для него используется специальный объект КлючЗаписи.

Пример обновления для справочника:


// В форме, где изменили данные
ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура"));
// Или передаем конкретную ссылку
ОповеститьОбИзменении(Объект.Ссылка);

Пример обновления для регистра сведений (используем совет из практики):


// Это заставит обновиться все списки данного регистра
ОповеститьОбИзменении(Тип("РегистрСведенийКлючЗаписи.ИмяВашегоРегистра"));

Преимущество этого метода в том, что нам не нужно писать программный код в форме-приемнике. Платформа сама найдет все открытые динамические списки, у которых в свойстве ОсновнаяТаблица указан данный регистр или справочник, и инициирует их обновление.

Различие между «ОбновитьОтображениеДанных» и «Прочитать»

Часто начинающие разработчики пытаются использовать метод ОбновитьОтображениеДанных(), но не видят результата. Проанализируем ситуацию и выясним, почему так происходит.

  1. ОбновитьОтображениеДанных() — этот метод не обращается к базе данных. Он всего лишь заставляет форму пересчитать условное оформление, проверить видимость и доступность кнопок, а также обновить значения, которые уже находятся на клиенте. Если данные в базе изменились, этот метод их не «увидит».
  2. ЭтаФорма.Прочитать() — этот метод (доступный для форм объектов) заставляет платформу полностью перезагрузить данные текущего объекта из базы данных на сервер, а затем передать их на клиент. Это «тяжелая» операция, но она гарантирует актуальность данных.
  3. Элементы.ИмяСписка.Обновить() — специализированный метод для динамических списков, который сбрасывает кэш списка и выполняет запрос к базе заново.

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

Продвинутые техники: обновление через параметры запроса

Бывают случаи, когда динамический список построен на сложном произвольном запросе, и обычные методы обновления не срабатывают из-за агрессивного кэширования платформы. В таких ситуациях мы можем применить небольшую хитрость.

Посмотрим на пример, где мы принудительно меняем параметр запроса, чтобы заставить систему пересчитать данные:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ТребуетсяПолноеОбновление" Тогда
        // Устанавливаем в параметр текущее время, чтобы запрос стал уникальным для кэша
        ТекущаяДатаСеанса = ТекущаяДата(); 
        Список.Параметры.УстановитьЗначениеПараметра("ВспомогательныйПараметр", ТекущаяДатаСеанса);
    КонецЕсли;
КонецПроцедуры

Этот подход гарантирует, что 1С выполнит запрос к базе «с нуля», проигнорировав старые закэшированные результаты.

Сценарий взаимодействия при работе с временным хранилищем

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

  1. В форме-источнике помещаем данные во Временное хранилище и получаем адрес.
  2. Вызываем Оповестить("ПереданыДанные", АдресХранилища).
  3. В форме-приемнике в процедуре ОбработкаОповещения получаем этот адрес.
  4. Вызываем серверный метод, который по адресу извлекает данные из хранилища и обрабатывает их.

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

Итоги и рекомендации

Подведем итог нашему анализу. Выбор метода зависит от архитектуры вашей задачи:

Используя эти механизмы, вы сможете создавать интерактивные и «живые» интерфейсы, которые мгновенно реагируют на действия пользователя в любой части системы.

← На главную