При работе с управляемыми формами разработчики 1С часто сталкиваются с ситуацией, когда событие ПриАктивизацииСтроки таблицы динамического списка вызывается чаще, чем пользователь действительно переключает строки. В некоторых случаях это приводит к повторной перерисовке формы, сбросу выделения на первую строку или бесконечным повторным обращениям к серверу.
В этой статье мы подробно разберем причины такого поведения платформы 1С и рассмотрим проверенные способы устранения проблемы.
Выделим основные технические причины, по которым событие ПриАктивизацииСтроки начинает зацикливаться или сбрасывать выделенную строку:
ПриАктивизацииСтроки вызывать серверный контекст (процедуру с директивой &НаСервере), платформа передает весь контекст формы на сервер и возвращает его обратно. При этом данные формы обновляются, что провоцирует повторную активизацию элементов.Самым популярным и стандартным решением этой проблемы (которое активно применяется в типовых конфигурациях) является перенос тяжелой логики в однократный обработчик ожидания. Это позволяет отложить выполнение серверных действий до момента, пока пользователь не прекратит быстрое перемещение по списку.
Рассмотрим пример реализации:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
// Отключаем предыдущий обработчик, если он был запущен
ОтключитьОбработчикОжидания("ОбработатьСменуСтроки");
// Подключаем однократный обработчик с задержкой 0.1 секунды
ПодключитьОбработчикОжидания("ОбработатьСменуСтроки", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьСменуСтроки()
ТекущаяСтрока = Элементы.Список.ТекущаяСтрока;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Здесь выполняем необходимые действия (включая работу с доступностью и сервером)
ОбновитьДоступностьИДанные(ТекущаяСтрока);
КонецПроцедуры
Чтобы избежать выполнения тяжелого кода при повторных или ложных срабатываниях события, рекомендуется сохранять идентификатор последней обработанной строки в переменной или реквизите формы и сравнивать его с текущей строкой.
Проанализируем пример кода с запоминанием идентификатора:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущаяСтрока = Элементы.Список.ТекущаяСтрока;
// Если строка не изменилась, выходим из процедуры
Если ТекущаяСтрока = ПоследняяОбработаннаяСтрока Тогда
Возврат;
КонецЕсли;
ПоследняяОбработаннаяСтрока = ТекущаяСтрока;
// Выполняем подгрузку данных или смену интерфейса
ОбновитьПодчиненныеДанные();
КонецПроцедуры
Если при смене строки вам необходимо получить детальные данные по выделенной записи с сервера, категорически избегайте контекстных вызовов. Используйте директиву &НаСервереБезКонтекста и передавайте только идентификатор строки или ключ данных.
Для получения идентификатора текущей строки динамического списка на клиенте обратитесь к функции ПолучитьИдентификатор() объекта ТекущиеДанные:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Получаем значение ключа или идентификатора строки
ИдентификаторЗаписи = ТекущиеДанные.Ссылка;
// Бесконтекстный вызов сервера не передает форму и не вызывает перерисовку списка
ДетальнаяИнформация = ПолучитьСведенияНаСервере(ИдентификаторЗаписи);
ЗаполнитьПоляФормы(ДетальнаяИнформация);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСведенияНаСервере(СсылкаНаОбъект)
// Выполнение запроса или получение данных без передачи контекста формы
Возврат Результат;
КонецФункции
Применяя комбинацию обработчика ожидания, проверки идентификатора строки на клиенте и бесконтекстных вызовов сервера, вы полностью исключите зацикливание события ПриАктивизацииСтроки и сброс позиционирования в динамическом списке.