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