Как программно установить картинку заголовка страницы и избежать бесконечного цикла в 1С

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

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

Выясняем причину зацикливания интерфейса

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

  1. Изменение свойства происходит на сервере (или требует синхронизации с серверным контекстом).
  2. После выполнения кода сервер возвращает клиенту обновленное описание формы.
  3. Клиентское приложение получает новое описание и перерисовывает интерфейс.
  4. Обновление состава или внешнего вида элементов формы платформа часто воспринимает как сигнал к повторной инициализации фокуса и состояния элементов.
  5. Это снова провоцирует вызов события ПриАктивизацииСтроки.

Так замыкается круг. Интересно, что установка пустой картинки через Новый Картинка часто не вызывает цикла, так как платформа оптимизирует отрисовку, если значение «пустое» или не изменилось. Но как только мы назначаем объект из БиблиотекаКартинок, цикл становится неизбежным.

Способ 1. Использование флага и обработчика ожидания

Разберем первый вариант решения, предложенный участниками обсуждения. Суть метода заключается в создании переменной-флага, которая будет блокировать повторный вход в процедуру, пока интерфейс не «успокоится».

Для реализации этого метода в модуле формы необходимо объявить переменную и создать вспомогательную процедуру. Рассмотрим пример кода:


&НаКлиенте
Перем КартинкаУстановлена;

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    // Проверяем, не вызвана ли процедура повторно системой
    Если КартинкаУстановлена = Истина Тогда
        Возврат;
    КонецЕсли;

    // Определяем, какую картинку нужно установить (логика зависит от ваших данных)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Устанавливаем картинку в зависимости от условий
    Если ТекущиеДанные.Статус = 4 Тогда
        Элементы.СтраницаОписаниеДетали.Картинка = БиблиотекаКартинок.ВосклицательныйЗнакКрасный;
    Иначе
        Элементы.СтраницаОписаниеДетали.Картинка = Новый Картинка;
    КонецЕсли; 

    // Включаем блокировку и взводим обработчик ожидания для её сброса
    КартинкаУстановлена = Истина;
    ПодключитьОбработчикОжидания("СброситьФлагУстановкиКартинки", 0.1, Истина);

КонецПроцедуры

&НаКлиенте
Процедура СброситьФлагУстановкиКартинки()
    КартинкаУстановлена = Ложь;
КонецПроцедуры

В данном примере ПодключитьОбработчикОжидания с параметром Истина выполнится всего один раз через 0.1 секунды. Этого времени достаточно, чтобы форма завершила цикл перерисовки, после чего флаг КартинкаУстановлена будет сброшен, и система снова будет готова реагировать на действия пользователя.

Способ 2. Сравнение текущего значения (самый оптимальный)

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

Если мы будем присваивать значение только тогда, когда оно реально отличается от текущего, платформа не будет инициировать бесконечную цепочку обновлений. Посмотрим на реализацию:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    НужнаяКартинка = БиблиотекаКартинок.Внимание16; // Пример логики выбора
    
    // Критически важная проверка:
    Если Элементы.СтраницаОписаниеДетали.Картинка <> НужнаяКартинка Тогда
        Элементы.СтраницаОписаниеДетали.Картинка = НужнаяКартинка;
    КонецЕсли;

КонецПроцедуры

Важный момент: этот способ отлично работает, если вы выбираете картинки из стандартной библиотеки. Платформа корректно сравнивает объекты картинок и, если они идентичны, повторного обновления формы и вызова события не происходит.

Способ 3. Контроль по идентификатору строки

Еще один профессиональный подход заключается в хранении идентификатора последней обработанной строки. Это гарантирует, что код смены оформления выполнится только один раз при переходе на новую строку, и проигнорирует все «технические» вызовы события при обновлении формы.

Рассмотрим, как это реализовать:

  1. Объявим переменную ПоследнийIDСтроки в начале модуля формы.
  2. В обработчике проверим текущий идентификатор.

&НаКлиенте
Перем ПоследнийIDСтроки;

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекущаяСтрока = Элемент.ТекущаяСтрока;
    
    // Если мы остались на той же строке, ничего не делаем
    Если ТекущаяСтрока = ПоследнийIDСтроки Тогда
        Возврат;
    КонецЕсли;
    
    // Запоминаем новую строку
    ПоследнийIDСтроки = ТекущаяСтрока;
    
    // Далее следует логика смены картинки
    // ...
    
КонецПроцедуры

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

Общие рекомендации по работе с ПриАктивизацииСтроки

Помните, что событие ПриАктивизацииСтроки крайне чувствительно к производительности. Старайтесь придерживаться следующих правил:

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

← На главную