Почему пропадает рамка кнопки или картинки при повторном нажатии в 1С и как это исправить?

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

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

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

Анализ причин: особенности рендеринга и потоковой разметки в 1С

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

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

  1. При первом нажатии свойство элемента меняется, и клиентское приложение инициирует отрисовку рамки.
  2. При повторном клике фокус ввода и внутреннее состояние элемента меняются интерактивно. Оптимизатор отрисовки считает, что элемент уже находится в активном состоянии и его визуальное представление не требует изменений. Происходит «пропуск» обновления графического буфера. В результате физически на экране рамка пропадает (или откатывается к дефолтному стилю), хотя логически в коде цвет назначен.
  3. Если параллельно с изменением цвета рамки в коде происходит переключение видимости других элементов или групп на форме, ситуация усугубляется. Скрытие или отображение групп (`Видимость = Ложь / Истина`) заставляет платформу полностью пересчитывать дерево элементов формы и заново перерисовывать интерфейс. Любые временные графические изменения, внесенные на клиенте «в обход» данных формы, при такой глобальной перерисовке просто сбрасываются.

Давайте подробно разберем, как решить эту проблему, начиная с исправления сопутствующих логических ошибок и заканчивая правильной архитектурной настройкой интерфейса.

Разбор сопутствующей ошибки: некорректная логика управления видимостью

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


Для Каждого Группа из ЭтаФорма.Элементы.ГруппыТоваров.ПодчиненныеЭлементы Цикл
    Если Группа.Имя <> "ГруппаТовара" + ТекущийТовар Тогда
        Группа.Видимость = Ложь;
    КонецЕсли;
КонецЦикла;

Давайте внимательно посмотрим на логику этого цикла. Мы обходим все подчиненные элементы и, если имя группы не совпадает с шаблоном текущего товара, устанавливаем свойство Видимость в значение Ложь. Однако в коде полностью отсутствует обратное действие! Если при изменении условий какая-то группа должна снова стать видимой, этот цикл ей видимость не вернет, так как ветка для значения Истина не предусмотрена.

Чтобы избежать подобных логических тупиков и сократить объем кода, рекомендуется использовать прямое присвоение булева выражения. Перепишем этот цикл правильно и лаконично:


Для Каждого Группа из ЭтаФорма.Элементы.ГруппыТоваров.ПодчиненныеЭлементы Цикл
    Группа.Видимость = (Группа.Имя = "ГруппаТовара" + ТекущийТовар);
    // Теперь видимость гарантированно установится либо в Истина, либо в Ложь
КонецЦикла;

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

Способ 1. Выполнение кода изменения оформления на сервере

Самый простой и быстрый способ решить проблему «исчезающей рамки» — перенести код, изменяющий цвет рамки и управляющий видимостью элементов, на сервер (в контекст сервера без контекста формы или с ним, в зависимости от логики). Именно так решил проблему автор темы на форуме.

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

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

Способ 2. Принудительное обновление отображения данных на клиенте

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

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


&НаКлиенте
Процедура ПриНажатииНаКнопкуТовара(Элемент)
    
    // Задаем цвет рамки нашей кнопке-картинке напрямую
    Элементы.КартинкаТовара.ЦветРамки = ЦветаСтиля.АкцентныйЦвет;
    
    // Логика управления видимостью смежных групп
    Для Каждого Группа из ЭтаФорма.Элементы.ГруппыТоваров.ПодчиненныеЭлементы Цикл
        Группа.Видимость = (Группа.Имя = "ГруппаТовара" + ТекущийТовар);
    КонецЦикла;
    
    // ПРИНУДИТЕЛЬНО заставляем платформу обновить все графические элементы
    ЭтаФорма.ОбновитьОтображениеДанных();
    
КонецПроцедуры

Метод ОбновитьОтображениеДанных() заставляет форму заново считать актуальные свойства оформления всех элементов интерфейса и принудительно перерисовать их на экране компьютера без обращения к серверу. Это решает проблему пропадающей рамки при повторных кликах.

Способ 3. Использование Условного оформления управляемой формы (Рекомендуемый стандарт)

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

Разберем этот метод пошагово:

  1. В реквизитах управляемой формы создадим новый реквизит (например, АктивныйТовар с типом Строка).
  2. Откроем свойства формы, перейдем на вкладку «Условное оформление» и добавим новое правило:
    • Оформление: выберем свойство «Цвет рамки» и укажем нужный нам цвет (например, Синий). Также можно задать толщину рамки.
    • Условие: задаем условие сравнения. Например: Объект.ИмяТовара Равно ИмяАктивнойКнопки (или сравниваем наш созданный реквизит формы: АктивныйТовар Не Равно "").
    • Оформляемые поля: указываем конкретный элемент формы (кнопку или поле картинки), к которому должно применяться это оформление.
  3. Теперь наш программный код на клиенте при нажатии кнопки становится предельно простым. Нам больше не нужно напрямую менять цвет рамки элемента — достаточно лишь обновить значение реквизита формы:

&НаКлиенте
Процедура ПриНажатииНаКнопкуТовара(Элемент)
    
    // Просто фиксируем, какая кнопка сейчас активна
    АктивныйТовар = Элемент.Имя; 
    
    // Платформа 1С автоматически на самом глубоком уровне оптимизации 
    // применит условное оформление и перерисует нужные рамки.
    
КонецПроцедуры

Использование условного оформления гарантирует, что рамки элементов никогда не «отвалятся» при повторных кликах, изменении видимости соседних групп или изменении размеров окна. Отрисовка условного оформления жестко контролируется самим ядром платформы.

Способ 4. Корректировка свойств кнопки в Конфигураторе

Иногда рамка кнопки или картинки пропадает из-за специфических настроек поведения фокуса. В платформе 1С у элементов типа «Кнопка» есть важное свойство — Отображение фигуры. Оно определяет, в какие моменты кнопка показывает свои границы и фон.

Посмотрим, какие значения может принимать это свойство и как их правильно настроить:

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

Также для выделения активных кнопок можно использовать стандартное свойство Пометка (тип Булево). При установке свойства Элементы.ИмяКнопки.Пометка = Истина платформа автоматически применяет к кнопке системный стиль «нажатого» состояния (выделение рамкой и фоном), который работает стабильно при любых действиях пользователя.

← На главную