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