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