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