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