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