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