Почему не работает ОбработкаОповещения и как правильно передать отбор в форму списка в 1С

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

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

Принцип работы механизма оповещений форм

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

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

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


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

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

Правильное открытие формы списка с установкой отбора

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

Разберем по шагам, как правильно сформировать параметры и открыть форму на клиенте:

  1. Создаем структуру ПараметрыФормы.
  2. Вкладываем в нее структуру Отбор, где ключами являются имена измерений или реквизитов регистра, а значениями — нужные условия.
  3. Вызываем метод ОткрытьФорму() в клиентском контексте.

Посмотрим на пример клиентского кода:


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

Обратите внимание: стандартная передача структуры в параметр Отбор автоматически накладывается платформой только на те поля регистра, которые являются измерениями либо реквизитами/ресурсами с установленным свойством Индексировать.

Установка жестких и сложных отборов через динамический список

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

Сначала передадим произвольные параметры при вызове формы:


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

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


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

Программное удаление записей регистра и обновление интерфейса

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


&НаСервере
Процедура УдалитьЗаписиРегистра(НомерЗадачи, Сотрудник)
    НаборЗаписей = РегистрыСведений.ЭтапыХронология.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.НомерЗадачи.Установить(НомерЗадачи);
    НаборЗаписей.Отбор.Сотрудник.Установить(Сотрудник);
    
    // Запись набора без добавления строк очищает соответствующие записи в базе данных
    НаборЗаписей.Записать();
КонецПроцедуры

После удаления записей на сервере вызовем на клиенте процедуру ОповеститьОбИзменении(). Это уведомит все открытые динамические списки системы о необходимости обновить данные на экранах пользователей:


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

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

← На главную