Почему не работает событие ОбработкаВыбора в 1С и как это исправить?

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

При разработке интерфейсов в среде 1С:Предприятие программисты часто сталкиваются с необходимостью кастомизировать стандартный процесс выбора значений в полях ввода или табличных частях. Для этого используется предопределенное событие НачалоВыбора, внутри которого устанавливается флаг СтандартнаяОбработка = Ложь. Однако на этом этапе многие совершают критическую ошибку: форма выбора открывается, но после непосредственного выбора элемента управление не возвращается в исходное поле, а событие ОбработкаВыбора попросту не вызывается.

В этой статье мы подробно разберем, почему возникает эта проблема, как работает механизм связи форм в платформе 1С, и рассмотрим практические варианты решения задачи как для обычных, так и для управляемых форм.

Суть проблемы: почему «ОбработкаВыбора» молчит?

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


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

На первый взгляд код выглядит логичным: мы отключили стандартное поведение, получили нужную форму выбора, установили фильтрацию по родителю (конкретной папке справочника) и открыли её. Но при тестировании в режиме отладки выясняется, что при двойном клике на строку в открывшемся окне выбора событие ТабличноеПоле1НаличиеЭЦПОбработкаВыбора не срабатывает. Выбранное значение не возвращается в исходную ячейку таблицы.

Выясним причину этого поведения. Когда мы устанавливаем СтандартнаяОбработка = Ложь, мы берем на себя полную ответственность за весь цикл выбора. Платформа больше не пытается угадать, куда именно нужно вернуть результат. Для того чтобы открываемая форма знала, какому объекту или элементу формы нужно передать выбранное значение, ей необходимо явно назначить Владельца. Без указания владельца открытая форма выбора функционирует как обычное независимое диалоговое окно.

Концепция владельца формы — ключ к решению

В 1С механизм возврата выбранного значения построен на жесткой связи «Владелец — Подчиненная форма». Если у формы выбора нет владельца:

  1. Она не понимает, что работает в режиме выбора (свойство РежимВыбора может сбрасываться).
  2. При двойном клике или нажатии кнопки «Выбрать» платформа вместо закрытия формы и возврата значения может открыть этот элемент на редактирование (карточку справочника).
  3. Вызывающий элемент формы-источника не получает никакого оповещения, и событие ОбработкаВыбора игнорируется.

Рассмотрим два основных способа решения этой проблемы в обычных формах.

Способ №1. Передача владельца в качестве параметра метода ПолучитьФормуВыбора

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


Процедура ТабличноеПоле1НаличиеЭЦПНачалоВыбора(Элемент, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // Передаем "Элемент" (наше табличное поле) вторым параметром
    Форма = Справочники.ОбъектыОИС.ПолучитьФормуВыбора(, Элемент); 
    
    Форма.ЭлементыФормы.СправочникСписок.ТекущийРодитель = Справочники.ОбъектыОИС.НайтиПоКоду("000000000000018");
    Форма.Открыть();
КонецПроцедуры

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

Способ №2. Явное назначение свойства ВладелецФормы

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


Процедура ТабличноеПоле1СотрудникНачалоВыбора(Элемент, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    ФормаПодбора = Справочники.Сотрудники.ПолучитьФормуВыбора();
    ФормаПодбора.РежимВыбора = Истина;
    ФормаПодбора.ЗакрыватьПриВыборе = Истина;
    
    // Явно указываем владельца формы
    ФормаПодбора.ВладелецФормы = Элемент; 
    
    ФормаПодбора.Открыть();
КонецПроцедуры

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

Реализация в управляемых формах (1С v8.3)

Хотя в исходной теме рассматриваются обычные формы, для полноты картины разберем, как эта задача решается в современных конфигурациях на управляемом приложении. Метод ПолучитьФормуВыбора там не используется. Вместо этого применяется метод ОткрытьФорму.

Связь с элементом-владельцем в управляемом интерфейсе передается третьим параметром метода. Разберем пример реализации:


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

После закрытия формы выбора платформа автоматически вызовет событие ОбработкаВыбора для элемента, который мы передали в качестве владельца.

Важность свойства «РежимВыбора» и метода «ОповеститьОВыборе»

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

Для решения этой проблемы необходимо соблюдать два правила:

  1. Убедиться, что у открываемой формы свойство РежимВыбора установлено в значение Истина.
  2. Если форма полностью произвольная, в ней необходимо программно инициировать возврат значения при выборе строки или нажатии на кнопку. Делается это с помощью метода ОповеститьОВыборе.

Рассмотрим, как выглядит отправка значения из произвольной формы:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    // Получаем данные выбранной строки
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Оповещаем владельца о сделанном выборе
        ОповеститьОВыборе(ТекущиеДанные.Ссылка);
    КонецЕсли;
КонецПроцедуры

Метод ОповеститьОВыборе посылает сигнал владельцу формы, передавая ему выбранное значение в качестве параметра, и закрывает текущую форму, если свойство ЗакрыватьПриВыборе установлено в Истина.

Резюме

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

← На главную