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