Почему не срабатывает событие ПриАктивацииСтроки при переключении между списками и как это исправить?

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

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

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

Разбор механики платформы: почему происходит «залипание»

Давайте разберем ситуацию с точки зрения ядра платформы 1С. Событие ПриАктивацииСтроки генерируется только тогда, когда внутри конкретного элемента управления (таблицы) изменяется индекс текущей строки. Рассмотрим пошагово проблемный сценарий:

  1. Пользователь работает в «Левом списке», активна Строка №1.
  2. Пользователь переходит в «Правый список», выполняет там действия. В «Левом списке» при этом по-прежнему остается выделенной (но не активной) Строка №1.
  3. Пользователь кликает обратно в «Левый список» именно по Строке №1.

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

Решение №1: Использование события ПриАктивацииЯчейки

Как показывает практика и эксперименты разработчиков, событие ПриАктивацииЯчейки срабатывает гораздо чаще и стабильнее, чем ПриАктивацииСтроки. Даже если вы используете режим выделения «Строка», платформа все равно отслеживает, в какую именно область (ячейку) был произведен клик мышкой.

Проанализируем пример кода, который позволяет минимизировать пропуски событий:


&НаКлиенте
Процедура ЛевыйСписокПриАктивацииЯчейки(Элемент)
    // Используем ТекущиеДанные для получения идентификатора
    ДанныеСтроки = Элементы.ЛевыйСписок.ТекущиеДанные;
    
    Если ДанныеСтроки <> Неопределено Тогда
        Гл_НомерЗаписи = ДанныеСтроки.НомерЗаписи;
        // Дополнительная логика обновления интерфейса
        ОбновитьИнформациюОЗаписи(Гл_НомерЗаписи);
    КонецЕсли;
КонецПроцедуры

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

Решение №2: Контроль контекстных серверных вызовов

Одной из скрытых причин «залипания» интерфейса являются неявные серверные вызовы внутри обработчиков активации. Рассмотрим типичную ошибку: программист обращается к реквизитам объекта или вызывает серверную функцию без параметров внутри ПриАктивацииСтроки.

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

Если серверный вызов необходим, попробуйте реализовать его через обработчик ожидания, чтобы дать форме завершить отрисовку фокуса:


&НаКлиенте
Процедура ЛевыйСписокПриАктивацииСтроки(Элемент)
    // Вместо прямого вызова сервера подключаем обработчик на 0.1 секунды
    ПодключитьОбработчикОжидания("ВыполнитьОбновлениеДанныхСервер", 0.1, Истина);
КонецПроцедуры

Решение №3: Комбинированный метод с ПриПолученииФокуса

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

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


&НаКлиенте
Процедура ЛевыйСписокПриПолученииФокуса(Элемент)
    // Принудительно вызываем логику активации, так как фокус вернулся в список
    ЛевыйСписокПриАктивацииСтроки(Элемент);
КонецПроцедуры

Решение №4: Прямая привязка данных (Data Binding)

Вместо того чтобы использовать модульные переменные типа Гл_НомерЗаписи и пытаться вручную присваивать им значения в коде, попробуйте использовать штатные механизмы платформы. Если на форме есть поле, которое должно отображать данные текущей строки, вы можете вынести его как Реквизит формы и связать его с путем к данным через Элементы.ЛевыйСписок.ТекущиеДанные.ИмяПоля.

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

Рекомендации по настройке платформы

Выясним причину зависимости от версии платформы. Начиная с релизов 8.3.16 и выше, работа с фокусом в управляемых формах стала более предсказуемой. Если вы используете версию 8.3.13.1690 (как автор вопроса) и сталкиваетесь с «залипаниями», рассмотрите следующие шаги:

  1. Режим совместимости: Убедитесь, что режим совместимости установлен в значение «Не использовать» или соответствует актуальной версии платформы.
  2. Обновление: По возможности перейдите на более свежий релиз (например, ветки 8.3.17 или 8.3.21). В них исправлено множество ошибок, связанных с событием OnActivateRow.
  3. Клавиши навигации: Помните, что перемещение клавишами Tab и Shift+Tab переводит фокус между элементами, но не всегда вызывает ПриАктивацииСтроки, если строка уже была выбрана. Для обработки навигации с клавиатуры использование ПриПолученииФокуса является обязательным.

Таким образом, для создания стабильного интерфейса с двумя списками мы рекомендуем комбинировать использование ПриАктивацииЯчейки, полностью исключить контекстные серверные вызовы и добавить обработку получения фокуса элементами управления. Это обеспечит четкую работу программы без необходимости «разблокировать» интерфейс лишними кликами.

← На главную