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