Как в обработке выбора узнать, из какого элемента формы-владельца была вызвана форма выбора

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

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

Способ 1. Использование обработчиков событий конкретных элементов

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

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

Алгоритм действий:

  1. Найдем в дереве элементов формы нужную таблицу или поле ввода.
  2. В свойствах элемента (в разделе «События») создадим обработчик ОбработкаВыбора.
  3. Пропишем логику заполнения именно для этого контекста.

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


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

Теперь в модуле формы документа мы будем работать не с общим событием, а со специфичным:


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

Способ 2. Применение механизма ОписаниеОповещения

Этот способ считается наиболее современным и гибким в среде управляемого приложения. Он позволяет полностью отказаться от использования владельца формы как единственного канала связи и передавать любой произвольный контекст через ДополнительныеПараметры.

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

Рассмотрим пример с двумя разными кнопками:


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

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

&НаКлиенте
Процедура ЗавершениеВыбораФизЛица(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = Неопределено Тогда
        Возврат; // Пользователь просто закрыл форму без выбора
    КонецЕсли;

    // Анализируем, из какой кнопки был вызов
    Если ДополнительныеПараметры.ИсточникВызова = "КнопкаЗаполнитьТЧ1" Тогда
        Сообщить("Заполняем первую таблицу для: " + Результат);
    ИначеЕсли ДополнительныеПараметры.ИсточникВызова = "КнопкаЗаполнитьТЧ2" Тогда
        Сообщить("Заполняем вторую таблицу для: " + Результат);
    КонецЕсли;
КонецПроцедуры

Способ 3. Передача идентификатора элемента через параметры формы

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

Посмотрим на пример реализации:


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

    ОткрытьФорму("Справочник.ФизическиеЛица.Форма.ФормаСписка", ПараметрыФормы, Элементы.Спецодежда);
КонецПроцедуры

В обработчике выбора на форме-владельце мы сможем прочитать этот параметр через ИсточникВыбора:


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    // ИсточникВыбора — это объект управляемой формы справочника
    Если ИсточникВыбора.Параметры.Свойство("ИмяИнициатора") Тогда
        ИмяЭлемента = ИсточникВыбора.Параметры.ИмяИнициатора;
        Сообщить("Выбор инициирован элементом: " + ИмяЭлемента);
    КонецЕсли;
КонецПроцедуры

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

Дополнительные рекомендации и нюансы

Проанализируем еще несколько важных моментов, которые помогут сделать код более надежным:

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

Выбор конкретного метода зависит от архитектуры вашей задачи. Для простых таблиц идеально подходит разделение обработчиков по элементам (Способ 1), а для сложных алгоритмов с передачей множества параметров — ОписаниеОповещения (Способ 2).

← На главную