Часто при разработке на управляемых формах 1С возникает задача программно установить курсор на определенную строку динамического списка, например, после обновления данных. Начинающие разработчики иногда пытаются обратиться к списку как к массиву элементов, используя конструкции вроде Элементы.МойСписок.ТекущаяСтрока = МойСписок[0].ПолучитьИдентификатор(), и в результате получают ошибку исполнения. Разберем по шагам, почему возникает эта ошибка и как правильно позиционировать курсор в различных ситуациях.
Проанализируем ситуацию. В платформе 1С динамический список не является ни массивом, ни таблицей значений. Это специализированный объект интерфейса, предназначенный для порционного чтения данных из базы. К нему нельзя обратиться по индексу строки, так как не все данные загружены в оперативную память.
Свойство ТекущаяСтрока элемента управляемой формы ожидает получить не абстрактный внутренний идентификатор или порядковый номер, а ключевое значение той таблицы, которая назначена в свойствах списка как основная.
Важно отметить: если динамический список построен на произвольном запросе и в его свойствах не задана основная таблица, платформа будет использовать внутренние порядковые номера строк. В таком режиме программное позиционирование на нужной записи работает нестабильно или игнорируется платформой.
Если в качестве основной таблицы динамического списка выступает объект ссылочного типа (например, справочник или документ), то ключом позиционирования является сама ссылка на этот объект.
Рассмотрим пример установки текущей строки для ссылочных типов. Ссылку необходимо предварительно получить запросом или сохранить в переменную:
// ИскомаяСсылка - переменная, содержащая ссылку на документ или элемент справочника
Элементы.МойСписок.ТекущаяСтрока = ИскомаяСсылка;
Если источником данных списка выступает регистр сведений, ситуация меняется. Поскольку ссылок у записей регистров не существует, ключом позиционирования выступает специальный объект — КлючЗаписи. Разберем подробнее, как его сформировать.
Вам необходимо создать структуру, содержащую значения всех измерений регистра (и периода, если регистр периодический), а затем на её основе получить ключ:
Отбор = Новый Структура;
Отбор.Вставить("Измерение1", Значение1);
Отбор.Вставить("Измерение2", Значение2);
// Получаем ключ записи регистра
Ключ = РегистрыСведений.ИмяРегистра.СоздатьКлючЗаписи(Отбор);
// Устанавливаем текущую строку в списке
Элементы.МойСписок.ТекущаяСтрока = Ключ;
Обновление данных динамического списка (через метод Обновить()) происходит асинхронно. Если сразу в следующей строке кода попытаться установить свойство ТекущаяСтрока, список может еще не успеть перечитать данные из базы. В результате позиционирование не сработает, и курсор сбросится на первую строку.
Посмотрим на надежные подходы для решения этой проблемы:
ОповеститьОбИзменении(Ссылка). Платформа перехватит оповещение, сама фоново обновит связанные с этой ссылкой динамические списки и автоматически сохранит позицию курсора без дополнительных строк кода.ПодключитьОбработчикОжидания с минимальной задержкой (0.1–0.5 секунды). В процедуре обработчика уже выполняется установка текущей строки. За это время платформа гарантированно успеет загрузить и отрисовать новые данные.Если требуется выполнить программное действие со списком, которое потенциально может сбить позиционирование, стандартной практикой является сохранение текущей позиции до начала действия и её восстановление после завершения.
Рассмотрим пример сохранения контекста:
// 1. Сохраняем текущую позицию
СохраненнаяСтрока = Элементы.МойСписок.ТекущаяСтрока;
// 2. Выполняем какие-либо действия...
// ...
// 3. Возвращаем фокус обратно
Элементы.МойСписок.ТекущаяСтрока = СохраненнаяСтрока;
Если после ваших манипуляций сохраненный объект пропал из списка (например, был удален или перестал попадать под наложенный отбор), установка значения будет просто проигнорирована платформой без вызова ошибки, что делает этот подход очень безопасным.