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

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

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

Разберем основную причину: некорректное определение владельца

Для того чтобы платформа «понимала», куда именно нужно вернуть выбранное значение, при открытии формы выбора необходимо четко указать её владельца. Рассмотрим ситуацию, когда форма открывается программно. Часто разработчики совершают ошибку, путая параметры в методах ПолучитьФорму и ОткрытьФорму.

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


ФормаВыборки = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора");
// ... установка параметров ...
ОткрытьФорму(ФормаВыборки,, Элемент); // Владелец передан вторым параметром в ОткрытьФорму

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


// Правильный способ №1: Передача владельца в ПолучитьФорму
ПараметрыФормы = Новый Структура("ТекущееЗначение", ТекущаяСсылка);
ФормаВыборки = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыФормы, Элемент);
ФормаВыборки.Открыть();

// Правильный способ №2: Использование ОткрытьФорму напрямую
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыФормы, Элемент);

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

Проблема передаваемых данных: ТекущиеДанные vs Ссылка

Выясним причину, по которой стандартный механизм может «проглатывать» событие. В управляемом приложении метод ОповеститьОВыборе ожидает данные, которые платформа может однозначно интерпретировать. Рассмотрим пример из обсуждения, где автор передает Элементы.Список.ТекущиеДанные.

Объект ТекущиеДанные имеет тип ДанныеФормыСтруктура. Если поле-владелец ожидает ссылку (например, СправочникСсылка.Номенклатура), а вы возвращаете структуру, платформа может заблокировать автоматическую обработку из-за несоответствия типов. Чтобы избежать этого, всегда старайтесь передавать конкретную ссылку:


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

Если же вам необходимо передать именно структуру (несколько значений сразу), вы обязательно должны перехватить это событие в форме-владельце, установив СтандартнаяОбработка = Ложь, иначе система попытается обработать выбор стандартно и не найдет подходящих по типу полей. Для реализации сложных сценариев типизации также существует универсальная форма выбора типа.

Анализируем свойство РежимВыбора

Посмотрим на настройки самой формы выбора. Чтобы форма вела себя именно как инструмент подбора, у неё должно быть установлено свойство РежимВыбора в значение Истина. Это можно сделать как в конфигураторе, так и программно при создании формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЭтаФорма.РежимВыбора = Истина;
КонецПроцедуры

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

Современный подход: использование ОписанияОповещения

Рассмотрим более надежный и гибкий метод, который рекомендуется для использования в современных конфигурациях (особенно в режиме «без модальности»). Вместо жесткой привязки к владельцу и ожидания события ОбработкаВыбора, мы можем использовать механизм обратного вызова (callback).

Пошаговый алгоритм реализации:

  1. В основной форме создаем процедуру-обработчик результата.
  2. При открытии формы выбора создаем объект ОписаниеОповещения.
  3. В форме выбора используем метод Закрыть(ЗначениеВыбора).

Пример кода в основной форме:


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

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

Пример кода в форме выбора:


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

Почему Оповестить() — это плохой вариант?

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

Используйте Оповестить() только для глобальных событий системы (например, «ОбновитьСписокЗаказов»), но никогда — для адресного возврата результата выбора.

Итоговый чек-лист для проверки:

  1. Владелец: Убедитесь, что в метод ОткрытьФорму или ПолучитьФорму передан правильный элемент (Элементы.ИмяТаблицы или ЭтаФорма).
  2. Тип данных: Проверьте, что возвращается Ссылка, а не структура ТекущиеДанные, если не предусмотрена ручная обработка структуры.
  3. Режим выбора: Убедитесь, что у открываемой формы свойство РежимВыбора установлено в Истина.
  4. Стандартная обработка: В обработчике ОбработкаВыбора попробуйте явно прописать СтандартнаяОбработка = Ложь.
  5. Экспорт: Если используете ОписаниеОповещения, убедитесь, что процедура обработки результата помечена ключевым словом Экспорт.

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

← На главную