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