Почему в обработчике события ОбработкаВыбора таблицы формы присутствует параметр Элемент, которого нет в справке?

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

При разработке управляемых форм в платформе «1С:Предприятие 8» разработчики часто сталкиваются со странным на первый взгляд несоответствием. Открывая встроенную справку или Синтакс-помощник для события какого-либо элемента управления, мы видим один набор параметров, но при автоматической генерации обработчика этого события в модуле формы платформа создает процедуру с дополнительным, самым первым параметром — Элемент. В этой статье мы подробно разберем, почему так происходит, как устроен этот архитектурный механизм платформы и как правильно использовать данный параметр в практической работе.

Архитектурный принцип платформы 1С: Модель отправителя события

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

ОбработкаВыбора(<ВыбранноеЗначение>, <СтандартнаяОбработка>)

Внутри контекста самого объекта ТаблицаФормы передавать ссылку на самого себя избыточно, так как объект функционирует в рамках собственного программного кода. Однако в модуле управляемой формы обработчики событий — это обычные процедуры-делегаты. Когда происходит интерактивное действие пользователя (например, выбор значения), платформе необходимо вызвать процедуру в модуле формы и передать ей контекст того элемента, который это событие инициировал.

Для реализации этого механизма платформа 1С использует классический паттерн программирования — модель отправителя события (Sender). Платформа всегда автоматически добавляет параметр Элемент первым аргументом в любой сгенерированный обработчик события элемента управления на форме. Это сквозной принцип, применимый абсолютно ко всем интерактивным событиям (таким как ПриИзменении, НачалоВыбора, Очистка и многим другим).

Практическая польза параметра Элемент: универсальность и повторное использование кода

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

  1. Назначение одного обработчика нескольким элементам формы. Представим ситуацию, когда на форме расположены две аналогичные таблицы или несколько полей ввода, требующих одинаковой логики обработки выбора. Вместо написания дублирующего кода для каждого элемента мы можем создать одну общую процедуру-обработчик и привязать её к событиям всех нужных элементов. Внутри этой процедуры мы легко определим, какой именно элемент вызвал событие, анализируя параметр Элемент (например, проверяя его имя через Элемент.Имя).
  2. Разработка универсальных алгоритмов и переносимого кода. Использование жестко прописанных имен элементов (Hardcoding) затрудняет перенос кода между различными формами и конфигурациями. Если в обработчике вместо конкретного имени Элементы.Материалы мы используем параметр Элемент, то такой код становится полностью универсальным. Его можно легко копировать в другой программный модуль без необходимости адаптации имен.
  3. Динамическое создание элементов формы. При программном создании элементов на форме в цикле мы можем динамически связывать их события с одним и тем же обработчиком в модуле. В этом случае параметр Элемент — единственный способ узнать, в какой именно программно созданной таблице или поле произошло действие.

Разница между ОбработкаВыбора для ТаблицыФормы и для УправляемойФормы

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

1. Событие элемента управления (ТаблицаФормы.ОбработкаВыбора):

Срабатывает тогда, когда выбор совершается в контексте конкретной таблицы или поля ввода. Сигнатура процедуры в модуле выглядит так:


&НаКлиенте
Процедура МатериалыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    // Наш код обработки
КонецПроцедуры

В этом обработчике присутствует параметр СтандартнаяОбработка. Установив его в значение Ложь, мы можем прервать стандартное поведение платформы (которая пытается автоматически записать выбранное значение в текущую ячейку таблицы) и реализовать собственный алгоритм: пересчитать цены, заполнить зависимые реквизиты строки или распределить данные по нескольким строкам табличной части.

2. Событие формы (УправляемаяФорма.ОбработкаВыбора):

Срабатывает на уровне всей формы, если владельцем открываемой формы выбора была указана сама форма (ЭтаФорма). Сигнатура процедуры в модуле:


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    // Наш код обработки на уровне формы
КонецПроцедуры

Обратите внимание: здесь нет параметра Элемент, так как контекстом выполнения является сама форма, а также отсутствует параметр СтандартнаяОбработка.

Как правильно связать форму выбора с таблицей формы

Разберем по шагам, как гарантировать попадание результата выбора именно в обработчик таблицы формы. Чтобы платформа корректно маршрутизировала событие, необходимо явно назначить таблицу в качестве владельца при открытии формы выбора. Рассмотрим пример кода:


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

Передавая Элементы.Материалы (тип ТаблицаФормы) в метод ОткрытьФорму, мы связываем форму выбора с нашей таблицей. Результат выбора автоматически вернется в процедуру МатериалыОбработкаВыбора.

Особенности работы и подводные камни в современных версиях платформы 1С

В актуальных версиях платформы 1С (включая последние релизы ветки 8.3) при работе с событиями выбора могут возникать неочевидные проблемы. Проанализируем ключевые из них и рассмотрим методы их решения:

Проблема невозврата значения. Иногда событие ОбработкаВыбора у таблицы-владельца вообще не вызывается. Обычно это происходит, если форма выбора закрывается стандартным методом Закрыть() без параметров или интерактивным крестиком в углу окна. Чтобы событие гарантированно отработало, в модуле формы выбора (или подбора) при интерактивном выборе строки обязательно должен выполняться вызов метода ОповеститьОВыборе(ВыбранноеЗначение).

Явное указание владельца при программном открытии. В последних релизах платформы автоматическое определение владельца при нестандартном открытии форм иногда сбоит. Для повышения отказоустойчивости приложения рекомендуется использовать явное связывание объектов перед открытием:


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

Обработка множественного выбора. Если у открываемой формы выбора включено свойство МножественныйВыбор = Истина, то в обработчик МатериалыОбработкаВыбора в качестве параметра ВыбранноеЗначение придет не одиночная ссылка, а объект типа Массив. Если в коде не сделать проверку типа, программа выдаст критическую ошибку при попытке записать массив в реквизит ячейки таблицы. Рассмотрим правильный шаблон обработки:


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

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

← На главную