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

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

В разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача создания связанных списков. Классический пример: при выборе контрагента в левом списке, в правом списке должны автоматически отображаться только его договоры или контактные лица. Рассмотрим подробно, как правильно реализовать этот механизм, чтобы он работал быстро, надежно и не перегружал сервер лишними вызовами.

Постановка задачи и базовый принцип реализации

Предположим, у нас есть общая форма, на которой размещены два реквизита типа ДинамическийСписок: СписокОсновной и СписокПодчиненный. Наша цель — сделать так, чтобы при перемещении курсора по основному списку данные во втором списке мгновенно (или с минимальной задержкой) обновлялись в соответствии с выбранным объектом.

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

Способ 1. Использование параметров запроса (Рекомендуемый)

Наиболее производительным способом считается использование параметров в тексте запроса динамического списка. В отличие от простых отборов компоновщика, параметры позволяют СУБД заранее подготовить план запроса, что ускоряет работу системы. Разберем по шагам:

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

Рассмотрим пример кода для реализации этой логики:


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

Способ 2. Оптимизация через обработчик ожидания

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

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

Реализуем это следующим образом:


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

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

Способ 3. Программная установка отбора

Если по каким-то причинам вы не хотите менять текст запроса (например, используется произвольный запрос, который нельзя редактировать), можно воспользоваться программной установкой отбора через КомпоновщикНастроек. Выясним, как это сделать правильно:


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

Важные нюансы и лучшие практики

Посмотрим на дополнительные аспекты, которые сделают ваш интерфейс более профессиональным:

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

← На главную