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