Как устранить «скачки» и нежелательное центрирование строк в динамическом списке при множественном выделении?

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

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

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

Выясним причину: почему платформа центрирует строки?

Давайте проанализируем ситуацию с точки зрения механизмов отрисовки управляемой формы. Основная причина кроется в событии ПриАктивизацииСтроки. Когда пользователь выделяет строку, система инициирует это событие. Если внутри обработчика происходит любое действие, которое платформа интерпретирует как изменение состояния формы, запускается цикл перерисовки (Form Refresh).

Рассмотрим основные триггеры перерисовки:

  1. Серверные вызовы: Даже если процедура помечена директивой &НаКлиенте, обращение к серверным методам формы или контекстным данным заставляет платформу синхронизировать состояние клиента и сервера. Это сбрасывает визуальное позиционирование списка.
  2. Изменение свойств элементов: Прямое изменение свойств Заголовок, Видимость, Доступность или ЦветТекста для кнопок, декораций или других полей формы.
  3. Условное оформление: Если оформление таблицы зависит от динамически меняющихся реквизитов, расчет которых происходит в момент активации строки.

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

Решение 1. Использование обработчика ожидания (самый надежный способ)

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

Разберем по шагам:

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


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

&НаКлиенте
Процедура ОбновитьИнтерфейсПослеВыделения()
    // Здесь выполняем все «тяжелые» или влияющие на интерфейс действия
    ВыделенныеСтроки = Элементы.Список.ВыделенныеСтроки;
    Количество = ВыделенныеСтроки.Количество();
    
    // Пример изменения заголовка кнопки без «прыжков» списка
    Элементы.ГруппаДействия.Заголовок = "Выбрано объектов: " + Количество;
КонецПроцедуры

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

Решение 2. Обновление через реквизиты формы (Data Path)

Рассмотрим ситуацию, когда вам нужно менять текст надписи или заголовок. Программное обращение к коллекции Элементы (например, Элементы.МояНадпись.Заголовок = ...) почти всегда приводит к перерисовке. Однако платформа оптимизирована для работы с данными.

Посмотрим на пример правильной реализации:

  1. Создайте в форме новый реквизит (например, ТекстИнформации с типом Строка).
  2. Вынесите этот реквизит на форму (например, в виде поля надписи или декорации).
  3. В свойстве элемента ПутьКДанным укажите ваш реквизит ТекстИнформации.

Теперь в коде вместо изменения свойства элемента, меняйте значение самого реквизита:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    // Прямое изменение реквизита формы часто проходит «бесшовно» для списка
    ТекстИнформации = "Выделено строк: " + Элементы.Список.ВыделенныеСтроки.Количество();
КонецПроцедуры

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

Решение 3. Использование метода «Оповестить»

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

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


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    Оповестить("ОбновитьСтатусСписка", , Элемент);
КонецПроцедуры

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

Как найти «скрытый» серверный вызов?

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

Частые ошибки, вызывающие неявный контекстный вызов:

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

← На главную