Как связать два динамических списка на управляемой форме в 1С?

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

Рассмотрим распространенную задачу при разработке и доработке конфигураций 1С. Часто возникает необходимость вывести на одну управляемую форму два динамических списка (ДС) и настроить их взаимосвязь. Например, первый список содержит перечень документов (скажем, «Приходная накладная»), а второй должен динамически отображать детализацию выбранного документа — его бухгалтерские проводки, движения по регистрам или подчиненные документы. Разберем по шагам, как правильно и оптимально реализовать такой механизм, чтобы не замедлить работу системы.

Основа логики: событие ПриАктивизацииСтроки

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

Базовая идея заключается в том, чтобы внутри этого обработчика получить ссылку на текущий документ и передать её во второй динамический список в качестве отбора или параметра. Однако прямая реализация обновления в этом событии таит в себе серьезную угрозу для производительности.

Почему критически важно использовать обработчик ожидания

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

Чтобы избежать этой проблемы, применим паттерн с использованием обработчика ожидания. Суть в том, чтобы отложить обновление второго списка на долю секунды. Пока пользователь листает список, таймер сбрасывается. Серверный вызов произойдет только тогда, когда курсор задержится на конкретной строке (например, на 0.3 секунды).

Рассмотрим пример реализации данного подхода:


&НаКлиенте
Перем ТекущаяСсылкаДляОтбора;

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Сохраняем ссылку в переменную модуля формы или реквизит
        ТекущаяСсылкаДляОтбора = ТекущиеДанные.Ссылка;
        
        // Подключаем обработчик ожидания на 0.3 сек (Истина - однократно)
        ПодключитьОбработчикОжидания("ОбновитьВторойСписокПоТаймеру", 0.3, Истина);
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьВторойСписокПоТаймеру()
    
    Если ЗначениеЗаполнено(ТекущаяСсылкаДляОтбора) Тогда
        УстановитьОтборВторогоСпискаНаСервере(ТекущаяСсылкаДляОтбора);
    КонецЕсли;
    
КонецПроцедуры

Параметры запроса или Отбор СКД: что выбрать?

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

  1. Использование параметров виртуальных таблиц. Если второй список выводит данные из регистров (бухгалтерии, накопления, сведений), настоятельно рекомендуется строить его произвольный запрос с использованием параметров. Например: ГДЕ Регистратор = &ТекущийДокумент. Передача значения через параметр (с помощью метода УстановитьПараметр у компоновщика настроек) отработает намного быстрее, так как СУБД получит оптимальный запрос к нужным разделам таблицы.
  2. Использование элементов отбора. Если второй список — это простой справочник или журнал документов, можно использовать отбор Системы Компоновки Данных (СКД). Для этого в типовых конфигурациях удобно применять готовую функцию: ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка().

Как правильно обращаться к программно созданному динамическому списку

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

Важно четко разделять две сущности управляемого приложения:

Чтобы установить параметр или отбор программно созданному списку, необходимо обращаться именно к реквизиту формы. Если список создан программно, платформа может не создать для него автоматическую переменную в контексте модуля. В таком случае к реквизиту формы необходимо обращаться строго через конструкцию ЭтаФорма.ИмяСписка (или ЭтаФорма["ИмяСписка"]). Попытка найти свойства СКД у визуального элемента таблицы неизбежно приведет к ошибке.

Альтернативный подход: ПриПолученииДанныхНаСервере

Рассмотрим альтернативу. Если задача второго списка состоит не в полноценной навигации, а лишь в выводе дополнительной информации (например, остаток по документу, текущий статус или связанные значения), начиная с платформы 1С 8.3.10 существует более элегантный подход. Можно обойтись вообще без второго списка, использовав событие первого списка ПриПолученииДанныхНаСервере.

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

← На главную