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