Как программно позиционировать текущую строку в начале таблицы значений в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах в платформе «1С:Предприятие 8» (особенно под мобильный клиент или мобильное приложение) разработчики часто сталкиваются с проблемой непредсказуемого поведения прокрутки (скроллинга) табличных частей и таблиц значений. Когда мы программно изменяем текущую строку таблицы, платформа самостоятельно решает, как именно прокрутить список. В результате целевая строка может оказаться в самом низу экрана, посередине или вверху. Такое поведение называют «ленивой прокруткой».

В этой статье мы подробно разберем, почему так происходит, изучим внутреннюю механику платформы 1С и рассмотрим красивое и простое решение, которое позволяет принудительно зафиксировать активированную строку в самом верху видимой области таблицы.

Понимание механики «ленивой прокрутки» в 1С

Для оптимизации производительности и снижения нагрузки на отрисовку интерфейса платформа 1С использует алгоритм минимального (или «ленивого») скроллинга для элементов управления типа «Таблица». Давайте проанализируем, как ведет себя система при изменении свойства ТекущаяСтрока:

  1. Строка уже находится в видимой области: Если строка, которую мы хотим сделать текущей, уже отображается на экране пользователя, платформа вообще не скроллит таблицу. Фокус просто перемещается на эту строку, а ее положение на экране остается прежним.
  2. Строка находится ниже видимой области: Если целевая строка расположена ниже текущего экрана, платформа прокручивает таблицу вниз ровно настолько, чтобы строка «показалась» на нижней границе экрана. В результате пользователь видит активированную строку на самом нижнем краю таблицы.
  3. Строка находится выше видимой области: Если целевая строка расположена выше текущего экрана, платформа прокручивает список вверх ровно настолько, чтобы строка показалась на самой верхней границе экрана.

Именно из-за этого алгоритма при последовательном переходе по кнопкам «Следующая группа» или «Предыдущая группа» фокус хаотично прыгает, раздражая пользователей и ухудшая юзабилити приложения.

Решение проблемы: Трюк с предварительным сбросом фокуса

Чтобы обойти ограничение ленивого скроллинга и гарантированно отобразить целевую строку на самом верху экрана, мы можем использовать простую двухшаговую комбинацию. Суть метода заключается в том, чтобы искусственно спровоцировать скроллинг платформы из заведомо верхней точки таблицы.

Разберем этот алгоритм по шагам:

  1. Сначала мы программно устанавливаем фокус на самую первую строку таблицы (строку с индексом 0). Это принудительно заставляет платформу мгновенно открутить скроллинг в самый верх.
  2. Сразу после этого мы устанавливаем фокус на нашу целевую строку. Поскольку фокус перемещается сверху вниз, платформа выполняет прокрутку, позиционируя целевую строку максимально близко к верхнему краю видимой области.

Посмотрим на практический пример реализации этого метода в коде:


// Предположим, что "СписокНоменклатуры" — это ТаблицаЗначений,
// а "Элементы.СписокНоменклатуры" — соответствующий элемент формы (Таблица).

&НаКлиенте
Процедура ПерейтиКСледующейГруппе(Команда)

    // Проверяем, что в таблице есть данные
    Если СписокНоменклатуры.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    // Шаг 1: Принудительно позиционируем фокус на самую первую строку таблицы.
    // Для этого получаем идентификатор первой строки (индекс 0).
    ИдентификаторПервойСтроки = СписокНоменклатуры[0].ПолучитьИдентификатор();
    Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторПервойСтроки;

    // Получаем идентификатор нашей целевой строки (например, первой строки следующей группы)
    ИдентификаторЦелевойСтроки = ПолучитьИдентификаторСледующейГруппы();

    // Шаг 2: Устанавливаем фокус на целевую строку.
    // Платформа выполнит скроллинг сверху вниз, и строка окажется вверху экрана.
    Если ИдентификаторЦелевойСтроки <> Неопределено Тогда
        Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторЦелевойСтроки;
    КонецЕсли;

КонецПроцедуры

Важное примечание: Метод ПолучитьИдентификатор() крайне важен, так как свойство ТекущаяСтрока у элемента формы типа «Таблица» ожидает именно уникальный идентификатор строки, а не саму строку таблицы значений или ее индекс.

Обратная задача: Позиционирование в самом низу

Используя ту же логику «ленивой прокрутки», мы можем легко решить обратную задачу. Если в вашем бизнес-процессе требуется, чтобы активированная строка гарантированно фиксировалась на нижней границе видимой области, необходимо выполнить зеркальные действия:

  1. Программно установить текущей самую последнюю строку таблицы значений. Это заставит платформу прокрутить весь список до самого конца вниз.
  2. Установить текущей целевую строку. Платформа будет вынуждена скроллить снизу вверх, благодаря чему целевая строка зафиксируется на нижней границе экрана.

Реализуется это следующим образом:


&НаКлиенте
Процедура ПозиционироватьВНизуЭкрана(ИдентификаторЦелевойСтроки)

    КоличествоСтрок = СписокНоменклатуры.Количество();
    Если КоличествоСтрок = 0 Тогда
        Возврат;
    КонецЕсли;

    // Шаг 1: Скроллим в самый низ таблицы
    ИндексПоследнейСтроки = КоличествоСтрок - 1;
    ИдентификаторПоследнейСтроки = СписокНоменклатуры[ИндексПоследнейСтроки].ПолучитьИдентификатор();
    Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторПоследнейСтроки;

    // Шаг 2: Возвращаемся снизу вверх к целевой строке
    Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторЦелевойСтроки;

КонецПроцедуры

Альтернативный метод: Позиционирование «ближе к центру»

Иногда позиционирование строго на верхней или нижней границе выглядит неестественно. Гораздо удобнее, когда текущая строка оказывается примерно по центру экрана, позволяя пользователю видеть контекст — несколько строк «до» и несколько строк «после».

Напрямую управлять пиксельным скроллингом или высотой строк в 1С нельзя. Однако мы можем использовать эмпирический метод «смещения» (офсета). Если мы примерно знаем, сколько строк помещается на экране устройства (например, на мобильном клиенте это обычно от 6 до 10 строк), мы можем рассчитать виртуальный сдвиг:


&НаКлиенте
Процедура ПозиционироватьПоЦентру(ИндексЦелевойСтроки)

    // Зададим среднее количество видимых строк на экране
    КоличествоВидимыхСтрок = 8; 
    Полусдвиг = Цел(КоличествоВидимыхСтрок / 2);

    КоличествоСтрок = СписокНоменклатуры.Количество();
    
    // Рассчитываем индекс строки, которую нужно временно активировать для сдвига
    ВременныйИндекс = ИндексЦелевойСтроки + Полусдвиг;
    
    // Проверяем, чтобы временный индекс не выходил за границы таблицы
    Если ВременныйИндекс >= КоличествоСтрок Тогда
        ВременныйИндекс = КоличествоСтрок - 1;
    КонецЕсли;

    // Шаг 1: Активируем нижнюю смещенную строку, чтобы подтянуть экран вниз
    ИдентификаторВременнойСтроки = СписокНоменклатуры[ВременныйИндекс].ПолучитьИдентификатор();
    Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторВременнойСтроки;

    // Шаг 2: Возвращаем фокус на реальную целевую строку
    ИдентификаторЦелевойСтроки = СписокНоменклатуры[ИндексЦелевойСтроки].ПолучитьИдентификатор();
    Элементы.СписокНоменклатуры.ТекущаяСтрока = ИдентификаторЦелевойСтроки;

КонецПроцедуры

Ограничения и опасности применения данного метода

Несмотря на простоту и эффективность описанных трюков, применять их следует с осторожностью, обращая внимание на тип источника данных вашей таблицы.

Важное предупреждение при работе с Динамическими Списками (ДинамическийСписок):

Описанные выше приемы отлично подходят для локальных коллекций, таких как ТаблицаЗначений или СписокЗначений, которые уже целиком находятся в памяти клиента. Однако, если ваша таблица на форме связана с объектом ДинамическийСписок (например, список справочника или документов), использование двойной программной смены текущей строки может привести к серьезным проблемам с производительностью:

Для динамических списков лучшим решением будет использование стандартных механизмов отбора или параметризации данных вместо попыток механической прокрутки больших объемов данных.

Особенности проектирования UI для мобильных устройств

При разработке интерфейсов под мобильный клиент 1С (где дефицит экранного пространства ощущается наиболее остро), постоянное программное «дерганье» экрана вверх и вниз может утомлять пользователя. В качестве альтернативы скроллингу рассмотрите следующие подходы к проектированию:

← На главную