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

Программист IT и автоматизация бизнеса
← На главную

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

Анализ проблемы: почему форма «летает» на сервер?

Первопричина проблемы кроется в механизме работы события ПриАктивизацииСтроки. Давайте проанализируем, что происходит в коде, когда мы пытаемся напрямую менять свойства элементов формы, такие как ЦветФона или Видимость. Согласно документации платформы 1С, событие ПриАктивизацииСтроки вызывается при любом изменении фокуса строки. Если внутри этого события мы меняем визуальное состояние элемента, платформа вынуждена выполнить серверный вызов для перерисовки графического интерфейса.

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

Решение №1: Использование Условного оформления вместо ручного управления цветом

Самый правильный и «чистый» способ изменить цвет элемента в зависимости от логики — это использование механизма Условного оформления. Вместо того чтобы в коде писать Элементы.Индикатор.ЦветФона = Новый Цвет(...), мы определим правило оформления заранее, а в коде будем менять только значение вспомогательного реквизита формы.

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

  1. Создадим реквизит формы СтатусМатериала (тип: Число).
  2. В настройках формы (закладка «Условное оформление») добавим два правила:
    • Если СтатусМатериала равен 1, то цвет фона индикатора — Зеленый.
    • Если СтатусМатериала равен 2, то цвет фона индикатора — Красный.
    • Если 0 — Белый (или прозрачный).
  3. В событии ПриАктивизацииСтроки мы просто меняем значение этого реквизита.

Посмотрим на пример кода, который исключает прямое обращение к свойствам элементов:


&НаКлиенте
Процедура ЗаказыПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элементы.Заказы.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        СтатусМатериала = 0; // Сбрасываем индикатор
        Возврат;
    КонецЕсли;

    // Вместо вызова сервера для изменения цвета, просто обновляем данные
    // Логика определения статуса может быть вынесена в серверную функцию без контекста
    СтатусМатериала = ПолучитьСтатусНаСервере(ТекущиеДанные.Ссылка);
    
КонецПроцедуры

Решение №2: Использование однократного обработчика ожидания

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

Проанализируем алгоритм:

  1. В событии ПриАктивизацииСтроки мы не выполняем полезную работу, а лишь регистрируем команду на обновление.
  2. Используем метод ПодключитьОбработчикОжидания с минимальным интервалом (например, 0.1 секунды) и параметром Однократно = Истина.

Пример реализации с использованием флага и обработчика:


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

&НаКлиенте
Процедура ВыполнитьОбновлениеИнтерфейса()
    // Здесь выполняем очистку выделения и другие действия
    Элементы.Материалы.ВыделенныеСтроки.Очистить();
    
    // Сбрасываем индикаторы
    СброситьИндикаторы();
КонецПроцедуры

Решение №3: Связь «Мастер-Деталь» через параметры динамического списка

Чтобы второй список ("Материалы") автоматически обновлялся при смене строки в первом ("Заказы") без лишнего написания кода, лучше всего использовать параметры динамического списка. Это избавляет нас от ручного формирования массивов на сервере.

Разберем, как это настроить:

В запросе динамического списка Материалы добавим условие:

ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&МатериалыЗаказа)

Теперь в обработчике активизации строки первого списка нам достаточно передать массив ссылок в этот параметр:


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

Важные рекомендации по работе с переменными

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

Совет: Всегда используйте Реквизиты формы для хранения состояния (например, СсылкаНаТекущийЗаказ, МассивМатериалов). Реквизиты формы автоматически передаются между клиентом и сервером и сохраняют свои значения в рамках сеанса работы с формой.

Резюме

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

Применяя эти подходы, вы добьетесь мгновенного отклика интерфейса и отсутствия «мерцания» формы при переходе между строками.

← На главную