Почему динамический список центрируется при активизации строки и как это исправить?

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

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

Разберем детально механизм возникновения этой проблемы и рассмотрим надежные способы ее решения.

Выясняем причину: почему список «прыгает» и центрируется

Проанализируем механику работы управляемой формы в платформе 1С:Предприятие 8.3:

  1. Пересчет геометрии управляемой формы (Layout): Любое изменение свойства Видимость, добавление или удаление элементов, а также изменение свойств Заголовок у кнопок и групп приводит к тому, что клиентский движок платформы выполняет полный перерасчет размеров и расположения всех элементов формы.
  2. Повторное позиционирование таблицы: В процессе перерасчета геометрии таблица, отображающая динамический список, вынуждена заново рассчитать свою видимую область. Платформа стремится гарантированно показать активную запись пользователю и выполняет стандартное центрирование выбранной строки. Если пользователь листал список вниз или вверх, позиция прокрутки сбивается.
  3. Частый вызов обработчика: Событие ПриАктивизацииСтроки срабатывает при каждом шаге курсора (включая быстрое перемещение стрелками клавиатуры). Постоянные пересчеты интерфейса создают визуальные рывки и замедляют работу клиента.
  4. Вызовы сервера: Если изменение свойств элементов или получение дополнительных данных строки выполняется через вызов сервера без контекста или с контекстом, это усугубляет задержки и провоцирует полное обновление данных формы.

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

Способ 1. Управление цветом текста и фона вместо видимости

Рассмотрим самый простой и действенный прием для отображения текстовых меток и надписей. Если требуется показывать или скрывать информационный текст (например, индикатор «Новинка», статус документа и т.д.), не следует менять свойство Видимость элемента вида Декорация — надпись.

Вместо скрытия элемента мы можем динамически менять цвет его текста. Когда надпись не должна отображаться, цвет ее текста устанавливается равным цвету фона формы (или делается полностью прозрачным), а при необходимости отображения — задается яркий цвет (например, красный или цвет стиля).

Посмотрим на пример клиентского кода в модуле формы:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем признак в текущей строке без серверных вызовов
    Если ТекущиеДанные.ЭтоНовинка Тогда
        Элементы.НадписьНовинка.ЦветТекста = ЦветаСтиля.ОсобыйТекст;
        Элементы.НадписьНовинка.Заголовок = "Новинка!";
    Иначе
        // Маскируем надпись цветом фона, не меняя размеры элемента
        Элементы.НадписьНовинка.ЦветТекста = ЦветаСтиля.ЦветФонаФормы;
        Элементы.НадписьНовинка.Заголовок = " ";
    КонецЕсли;

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

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

Способ 2. Изменение доступности вместо видимости элементов и команд

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

Правильный подход — управлять свойством Доступность кнопки или связанной с ней команды:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Меняем доступность команды формы
    Команды.ВыполнитьСпециальноеДействие.Доступность = ТекущиеДанные.РазрешеноДействие;

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

Свойство Доступность делает элемент неактивным (серым), сохраняя его геометрические размеры на панели, благодаря чему таблица списка не центрируется.

Способ 3. Использование группы страниц с фиксированным размером

Если бизнес-логика строго требует отображения совершенно разных наборов элементов управления в зависимости от выбранной строки, используем структуру закладок без отображения страниц:

  1. Создаем группу формы с видом Страницы.
  2. В свойствах группы страниц устанавливаем ОтображениеЗакладок = НеОтображать.
  3. Внутри создаем несколько страниц (например, СтраницаДействияНовинки и СтраницаОбычныеДействия).
  4. На каждой странице размещаем необходимый состав кнопок и полей.
  5. Для группы страниц явно задаем фиксированную высоту и ширину, чтобы переключение страниц не вызывало изменения внешних габаритов контейнера.

В коде события ПриАктивизацииСтроки переключаем активную страницу через свойство ТекущаяСтраница:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ТекущиеДанные.ЭтоНовинка Тогда
        Элементы.ГруппаПанелейКнопок.ТекущаяСтраница = Элементы.СтраницаНовинки;
    Иначе
        Элементы.ГруппаПанелейКнопок.ТекущаяСтраница = Элементы.СтраницаСтандартная;
    КонецЕсли;

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

Так как страницы уже встроены в разметку и обладают одинаковой геометрией, переключение между ними происходит на клиенте мгновенно и не провоцирует смещение строк в таблице.

Способ 4. Перенос индикации в условное оформление динамического списка

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

Разберем настройку:

  1. Открываем свойства динамического списка и переходим в пункт Условное оформление.
  2. Добавляем элемент оформления: задаем цвет фона, цвет текста или шрифт.
  3. В условии указываем: ЭтоНовинка Равно Истина.
  4. В оформляемых полях выбираем всю строку или конкретную колонку (например, Наименование).

Вся отрисовка в этом случае выполняется платформой нативно внутри самой таблицы. Код в событии ПриАктивизацииСтроки вообще не требуется, что полностью исключает любые артефакты отображения и центрирование списка.

Способ 5. Использование обработчика ожидания для снижения нагрузки

Если тяжелые действия при смене строки неизбежны, вызов логики обновления следует отделять от момента перемещения курсора с помощью однократного обработчика ожидания:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    // Перезапускаем однократный обработчик с небольшой задержкой
    ОтключитьОбработчикОжидания("ВыполнитьОбновлениеИнтерфейса");
    ПодключитьОбработчикОжидания("ВыполнитьОбновлениеИнтерфейса", 0.1, Истина);

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

&НаКлиенте
Процедура ВыполнитьОбновлениеИнтерфейса()
    
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Выполняем действия только тогда, когда пользователь остановил скролл
    ОбновитьСостояниеПанелей(ТекущиеДанные);

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

Этот прием предотвращает многократные перерисовки формы во время быстрого листания таблицы списка клавишами со стрелками или колесом мыши.

← На главную