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