Разработка и Конфигурация · 10 мин
Событие ПриАктивизацииСтроки в 1С: когда срабатывает и как правильно использовать
Разбираем событие ПриАктивизацииСтроки в 1С: когда оно вызывается, порядок срабатывания, типичные ошибки, отличия от ПриАктивизацииЯчейки и практические примеры кода.
Событие ПриАктивизацииСтроки в 1С вызывается у табличного поля (обычные формы) или таблицы формы (управляемые формы) каждый раз, когда пользователь или программный код переводит активность на другую строку таблицы. Это одно из самых часто используемых событий при доработке форм списков, подборов и документов: на него «вешают» обновление связанных данных, отображение картинки, расчёт итогов по текущей строке, управление доступностью кнопок.
Проблема в том, что событие срабатывает гораздо чаще, чем ожидают начинающие разработчики: при первом открытии формы, при программном изменении текущей строки, при перерисовке таблицы, иногда — дважды подряд. Если в обработчике разместить тяжёлый запрос или код, меняющий данные формы, можно получить «подвисание» интерфейса или зацикливание. Поэтому важно точно понимать моменты вызова и ограничения.
Ниже разобраны конкретные ситуации срабатывания, отличия поведения в обычных и управляемых формах, порядок вызова относительно других событий и приёмы защиты от лишних вызовов.
В каких ситуациях срабатывает событие
Событие вызывается платформой всякий раз, когда меняется активная (текущая) строка табличного элемента. Конкретные триггеры:
- пользователь щёлкнул мышью по другой строке;
- пользователь переместился клавишами вверх/вниз, PageUp/PageDown;
- код установил текущую строку:
Элементы.Список.ТекущаяСтрока = НужнаяСсылка;или изменилТекущиеДанные; - форма открылась, таблица заполнилась, и платформа автоматически активизировала первую строку;
- список обновился (например, после записи элемента), и текущая строка была восстановлена платформой;
- применился отбор или поиск, изменивший состав строк, и активной стала другая строка.
Важный нюанс: если таблица пустая, активной строки нет и событие не вызывается. Если при открытии формы строка одна — событие всё равно сработает один раз, когда платформа её активизирует.
Ещё одна ситуация, о которой часто забывают: программная установка текущей строки из кода вызывает событие так же, как и действие пользователя. Если внутри обработчика вы снова меняете текущую строку — получаете повторный вызов и потенциальный бесконечный цикл.
Событие вызовется один раз на каждую смену строки
Платформа активизирует первую строку — событие сработает
Событие сработает, если строка реально изменилась
Событие не вызывается — активной строки нет
Порядок срабатывания относительно других событий формы
Понимание последовательности помогает не размещать логику «не в том» обработчике. Типичная цепочка при открытии формы списка в управляемом приложении: ПриСозданииНаСервере → ПриОткрытии → ПриАктивизацииСтроки (когда платформа активизирует первую строку списка). В обычных формах аналогично: ПриОткрытии → активация строки табличного поля.
Внутри таблицы события выстраиваются так: сначала ПриАктивизацииСтроки, затем ПриАктивизацииЯчейки (если активизировалась конкретная колонка), затем ПриАктивизацииПоля. При начале редактирования строки дополнительно вызываются ПередНачаломИзменения и ПриНачалеРедактирования.
Практический вывод: код, который должен выполниться один раз при открытии, размещайте в ПриСозданииНаСервере или ПриОткрытии, а не в ПриАктивизацииСтроки — иначе он будет выполняться при каждом перемещении по списку.
Отличия в обычных и управляемых формах
В обычных формах событие назначается табличному полю и срабатывает строго на клиенте, обработчик пишется в модуле формы. Поведение предсказуемое: один переход — один вызов.
В управляемых формах событие назначается таблице формы (элементу, связанному с динамическим списком или таблицей значений). Здесь есть особенности:
- обработчик выполняется на клиенте, но если в нём вызывается серверная процедура — каждый переход по строкам порождает серверный вызов, что заметно тормозит работу;
- при обновлении динамического списка событие может сработать повторно, даже если пользователь не двигал курсор — платформа заново активизирует строку;
- для динамических списков рекомендуется использовать вместо прямого обработчика механизм ожидания:
Элементы.Список.ОбновитьОтображениеДанных()не вызывает событие, а вот смена текущей строки — вызывает.
Типовой приём: отложенная обработка через обработчик ожидания
Классическая задача — при переходе по строкам списка показывать подробную информацию по текущему элементу (остатки, картинку, связанные документы). Если делать запрос в самом обработчике, при быстром перемещении клавишей «вниз» получим десяток запросов подряд.
Решение — в ПриАктивизацииСтроки только подключить одноразовый обработчик ожидания с коротким интервалом, а всю тяжёлую работу выполнять в нём:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ПодключитьОбработчикОжидания("ОбновитьДеталиТекущейСтроки", 0.2, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДеталиТекущейСтроки()
ТекДанные = Элементы.Список.ТекущиеДанные;
Если ТекДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ПоказатьДеталиНаСервере(ТекДанные.Ссылка);
КонецПроцедуры
Так при серии быстрых переходов тяжёлый код выполнится один раз — после того, как пользователь «остановился» на нужной строке. Интервал 0.1–0.3 секунды обычно достаточен и незаметен для пользователя.
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ПодключитьОбработчикОжидания("ОбновитьДетали", 0.2, Истина);
КонецПроцедурыТипичные ошибки и как их избежать
Первая и самая опасная ошибка — изменение состава строк или текущей строки внутри обработчика. Удаление строк, установка отбора, присвоение ТекущаяСтрока провоцируют повторный вызов события, и форма уходит в цикл вплоть до аварийного завершения сеанса.
Вторая ошибка — тяжёлые запросы и серверные вызовы без задержки, описанная выше. Третья — отсутствие проверки на Неопределено: когда таблица пуста или строка ещё не активизирована, ТекущиеДанные равны Неопределено, и обращение к полям строки вызовет ошибку.
Четвёртая — модификация данных объекта в обработчике. Событие предназначено для чтения и отображения, а не для изменения данных. Если нужно реагировать на изменение значения в строке — используйте ПриИзменении поля или ПриОкончанииРедактирования.
Чем заменить событие, если оно не подходит
Не каждую задачу нужно решать через ПриАктивизацииСтроки. Варианты альтернатив:
ПриАктивизацииЯчейки— если реакция нужна только при переходе в конкретную колонку;ПриИзмененииу поля ввода — если важно изменение значения, а не смена строки;Выбор— если нужна реакция на двойной клик или Enter (открытие объекта);- для динамических списков — обработка на уровне команд формы и контекстных меню, если действие инициирует пользователь явно.
Какое событие выбрать
Нужно реагировать на сам факт смены текущей строки: подсветка, детали, доступность кнопок
Реакция зависит от конкретной колонки, в которую перешёл пользователь
Важно изменение значения в поле, а не переход по строкам
Нужно открытие объекта или действие по двойному клику / Enter
Как проверить, что обработчик работает правильно
После доработки пройдите контрольный сценарий: откройте форму (событие должно сработать один раз), пройдитесь клавишами по нескольким строкам (по одному вызову на строку), быстро «пролистайте» список — тяжёлая логика должна сработать один раз после остановки. Проверьте поведение на пустом списке и на списке из одной строки.
Для отладки удобно временно добавить Сообщить("Активизирована строка: " + ТекДанные.Ссылка); или точку останова в отладчике — так видно реальное количество вызовов.
Как проверить результат
Один вызов при активизации первой строки
Многократные вызовы или ошибка до появления формы
Интерфейс не тормозит, тяжёлая логика срабатывает после остановки
Форма подвисает на каждом переходе
Обработчик не падает, ТекущиеДанные проверены на Неопределено
Ошибка обращения к полям строки
Состояние формы корректно восстанавливается
Зацикливание или сброс текущей строки
Что важно запомнить
ПриАктивизацииСтроки срабатывает при любой смене активной строки — пользовательской и программной, включая открытие формы. В обработчике только читаем данные и обновляем отображение, тяжёлую логику выносим в отложенный обработчик ожидания, а состав строк и текущую строку не трогаем.
Частые вопросы
Почему ПриАктивизацииСтроки срабатывает два раза подряд?
Чаще всего это происходит в управляемых формах при обновлении динамического списка: платформа сначала сбрасывает активную строку, затем активизирует её заново. Также двойной вызов бывает, если в самом обработчике код косвенно меняет текущую строку. Проверьте обработчик на побочные действия и при необходимости добавьте флаг «обработка уже выполняется».
Срабатывает ли событие при открытии формы?
Да, если в таблице есть данные: платформа автоматически активизирует первую строку, и событие вызывается. Если список пуст — события не будет. Поэтому код инициализации, который должен выполниться строго один раз, лучше размещать в ПриСозданииНаСервере.
Как получить данные активной строки в обработчике?
В управляемой форме — через Элементы.ИмяТаблицы.ТекущиеДанные (обязательно с проверкой на Неопределено). В обычной форме — через ЭлементыФормы.ИмяТабличногоПоля.ТекущиеДанные или параметр Элемент обработчика.
Можно ли в обработчике менять текущую строку?
Технически можно, но это вызовет повторное срабатывание события и риск зацикливания. Если переход нужен, делайте его вне обработчика — например, через обработчик ожидания или по команде пользователя.
Чем ПриАктивизацииСтроки отличается от ПриАктивизацииЯчейки?
ПриАктивизацииСтроки вызывается при смене строки целиком, ПриАктивизацииЯчейки — при переходе в конкретную ячейку, в том числе при горизонтальном перемещении внутри той же строки. Если реакция должна зависеть от колонки, используйте второе событие.
Тормозит форма при переходе по списку — что делать?
Почти всегда причина в тяжёлом коде (запрос, серверный вызов) прямо в обработчике. Оставьте в нём только ПодключитьОбработчикОжидания с интервалом 0.1–0.3 секунды и флагом однократности, а запросы выполняйте в вызываемой им процедуре.