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

Программист 1С v8.3 (Обычные формы)
← На главную

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

Почему возникает мелькание? Проблема метода Сбросить()

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


ЭлементыФормы.ТЧ.ОтборСтрок.Сбросить();
ЭлементыФормы.ТЧ.ОтборСтрок.Заказчик.Установить(ТекущийЗаказчик);
ЭлементыФормы.ТЧ.ОтборСтрок.Закрыт.Установить(флЗакрытия);

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

Важный нюанс: даже если вы не используете Сбросить(), но меняете несколько полей отбора через Установить(), каждое такое изменение может инициировать отдельное обновление интерфейса.

Решение 1. Прямой перебор коллекции отборов (оптимальный способ)

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

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


// Получаем коллекцию отборов напрямую
Отбор = ЭлементыФормы.ТЧ.ОтборСтрок;

// Проходим циклом по всем доступным полям отбора
Для Каждого ЭлементОтбора Из Отбор Цикл
    Если ЭлементОтбора.Имя = "Заказчик" Тогда
        ЭлементОтбора.Значение = ТекущийЗаказчик;
        ЭлементОтбора.Использование = Истина;
    ИначеЕсли ЭлементОтбора.Имя = "Закрыт" Тогда
        ЭлементОтбора.Значение = флЗакрытия;
        ЭлементОтбора.Использование = Истина;
    Иначе
        // Все остальные фильтры, которые могли быть установлены ранее, отключаем
        ЭлементОтбора.Использование = Ложь;
    КонецЕсли;
КонецЦикла;

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

Решение 2. Правильный порядок установки параметров

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

Неправильно: сначала включаем использование, потом меняем значение.


Отбор.Заказчик.Использование = Истина; // Система может начать фильтрацию по пустому значению
Отбор.Заказчик.Значение = ТекущийЗаказчик;

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


Отбор.Заказчик.Значение = ТекущийЗаказчик;
Отбор.Заказчик.ВидСравнения = ВидСравнения.Равно;
Отбор.Заказчик.Использование = Истина; // Только теперь система пересчитывает таблицу

Такой подход минимизирует количество промежуточных пересчетов видимости строк.

Решение 3. Использование служебной колонки-индекса

Если ваша табличная часть содержит сложные условия (например, нужно отфильтровать строки по сумме условий из пяти разных колонок), стандартный ОтборСтрок может работать медленно, вызывая фризы интерфейса. В этом случае мы рекомендуем применить метод «Индекса фильтра».

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

  1. Добавим в таблицу (в объекте или в коде программно) скрытую колонку СлужебныйФлагОтбора (тип Булево).
  2. При смене условий (например, нажатии на закладку) запустим цикл по всей таблице и рассчитаем значение для этой колонки.
  3. Установим один единственный отбор по колонке СлужебныйФлагОтбора = Истина.

Пример реализации:


// 1. Рассчитываем признак видимости строк
Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧасть Цикл
    СтрокаТЧ.СлужебныйФлагОтбора = (СтрокаТЧ.Заказчик = ТекущийЗаказчик) И (СтрокаТЧ.Закрыт = флЗакрытия);
КонецЦикла;

// 2. Накладываем один простой отбор
ЭлементыФормы.ТабличнаяЧасть.ОтборСтрок.СлужебныйФлагОтбора.Установить(Истина);

Поскольку меняется только один параметр фильтрации, графическая оболочка перестраивается один раз, что практически полностью исключает мелькание.

Решение 4. Управление отрисовкой окна через WinAPI

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

Суть метода заключается в следующем:

  1. Перед началом любых манипуляций с отборами окну табличного поля посылается команда на запрет отрисовки.
  2. Выполняются все программные действия (сброс, установка новых значений, циклы).
  3. Окну посылается команда на разрешение отрисовки и принудительное обновление.

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

Рекомендации по оптимизации производительности

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

  1. Условное оформление: Если на табличную часть наложены правила оформления (например, выделение цветом строк с определенным статусом), то при каждой смене отбора платформа пересчитывает цвета для всех строк. Постарайтесь минимизировать количество условий в ПриВыводеСтроки или ПриПолученииДанных.
  2. Объем данных: Для таблиц объемом более 1000 строк стандартный ОтборСтрок в обычных формах работает неэффективно. В таких случаях стоит рассмотреть возможность использования ПостроителяЗапроса, который подготовит выборку в памяти, и последующую выгрузку результата в таблицу.
  3. Видимость элементов: Не стоит использовать ЭлементыФормы.ТЧ.Видимость = Ложь на время смены отбора. Это создает еще больший дискомфорт для глаз пользователя, так как вся таблица исчезает и появляется снова.

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

← На главную