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