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