При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с ситуацией, когда бизнес-логика завязана на событие ПриАктивизацииСтроки динамического списка. Например, при перемещении по списку контрагентов в соседнем окне должны отображаться их контактные лица или история звонков. Однако при использовании стандартного поиска (Ctrl+F) или строки поиска в заголовке списка это событие может не срабатывать, даже если визуально в списке осталась всего одна строка и она подсвечена. Для реализации подобного механизма можно использовать пример связывания главной и подчиненной таблиц на управляемых формах.
В этой статье мы подробно разберем, почему платформа ведет себя именно так, и рассмотрим несколько надежных способов решения этой задачи.
Событие ПриАктивизацииСтроки генерируется платформой в тот момент, когда фокус перемещается с одной строки на другую. Ключевое слово здесь — перемещение. Рассмотрим внутреннюю механику работы стандартного поиска:
ТекущаяСтрока (идентификатор строки) не изменилась.Поскольку идентификатор активной строки остался прежним, событие активации не вызывается, так как фокус формально никуда не переходил. Ситуация усложняется, когда в списке после фильтрации остается всего одна строка: она визуально выделяется пунктиром или цветом, но программно она может даже не считаться "текущей", пока пользователь явно не кликнет по ней мышью.
Разберем по шагам реализацию "ленивого мониторинга" состояния списка. Поскольку у нас нет прямого события "После окончания поиска", мы заставим форму периодически проверять, не изменилась ли активная строка.
Рассмотрим пример реализации кода:
&НаКлиенте
Перем ПредыдущаяСтрока; // Глобальная переменная модуля формы
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ПроверитьОбновлениеАктивнойСтроки", 0.3);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьОбновлениеАктивнойСтроки()
ТекущаяСтрока = Элементы.Список.ТекущаяСтрока;
// Проверяем, изменился ли идентификатор строки
Если ТекущаяСтрока <> ПредыдущаяСтрока Тогда
ПредыдущаяСтрока = ТекущаяСтрока;
// Здесь вызываем процедуру, которая должна была сработать ПриАктивизацииСтроки
ВыполнитьЛогикуПриСменеСтроки(ТекущаяСтрока);
КонецЕсли;
КонецПроцедуры
Важный нюанс: использование интервала 0.3 секунды является оптимальным. Это достаточно быстро, чтобы пользователь не заметил задержки, и достаточно редко, чтобы не создавать избыточную нагрузку на клиентское приложение.
Для более чистого и контролируемого кода мы можем отказаться от стандартной строки поиска в пользу собственной. Это позволит нам точно знать, когда поиск начался и когда он закончился. Рассмотрим, как это реализовать.
СтрокаПоиска (тип Строка).ПриИзменении этого поля пропишем программную установку отбора.
&НаКлиенте
Процедура СтрокаПоискаПриИзменении(Элемент)
// Устанавливаем отбор через компоновщик настроек
Настройка = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
Настройка.Элементы.Очистить();
Если Не ПустаяСтрока(СтрокаПоиска) Тогда
ЭлементОтбора = Настройка.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
ЭлементОтбора.ПравоеЗначение = СтрокаПоиска;
ЭлементОтбора.Использование = Истина;
КонецЕсли;
// Принудительно заставляем список обновиться
Элементы.Список.Обновить();
// А теперь — самое главное: программно активируем первую строку
Если Элементы.Список.ДанныеСтроки(Элементы.Список.ТекущаяСтрока) = Неопределено Тогда
// Здесь можно реализовать логику позиционирования на первую доступную строку
КонецЕсли;
КонецПроцедуры
Проанализируем этот подход: он позволяет нам вручную вызвать событие ПриАктивизацииСтроки или просто выполнить нужную нам функцию сразу после обновления фильтра, не дожидаясь действий пользователя.
У динамического списка существует стандартное событие ПриОбновленииСоставаДанных. Оно вызывается платформой каждый раз, когда данные в списке перечитываются (включая применение стандартного поиска).
Рассмотрим, как его использовать правильно, чтобы избежать зацикливания и падения производительности:
ПриОбновленииСоставаДанных для таблицы списка.ТекущаяСтрока.
&НаКлиенте
Процедура СписокПриОбновленииСоставаДанных(Элемент)
// Это событие вызывается на клиенте при любом изменении состава строк
// Используем его для синхронизации данных, если ТекущаяСтрока визуально "подвисла"
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Выполняем действия по обновлению связанных элементов интерфейса
ОбновитьСвязаннуюИнформацию(ТекущиеДанные.Ссылка);
КонецЕсли;
КонецПроцедуры
Внимание: Будьте осторожны с этим событием. Оно срабатывает очень часто (при прокрутке, обновлении, поиске), поэтому внутри него нельзя размещать тяжелые серверные вызовы без предварительной проверки условий.
Подведем итог нашему исследованию:
Важно помнить, что в 1С:Предприятие 8.3 управляемые формы стремятся минимизировать количество вызовов между клиентом и сервером, поэтому иногда отсутствие события ПриАктивизацииСтроки — это не ошибка, а оптимизация платформы. Понимая эти механизмы, мы можем строить более отзывчивые и надежные интерфейсы.