Как получить цвета стиля в тонком клиенте 1С:Предприятие 8?

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

Разработчики управляемого интерфейса в платформе «1С:Предприятие 8.3» часто сталкиваются с необходимостью динамического управления визуальным оформлением форм. Это может быть выделение полей ввода, изменение цвета фона кнопок, раскраска строк динамических списков или создание кастомных тем оформления для пользователей. Логичным решением в таком случае кажется использование предопределенного системного набора ЦветаСтиля. Однако при попытке обратиться к нему напрямую в клиентском коде тонкого клиента система выдает критическую ошибку о том, что переменная не определена.

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

Выясним причину: почему цвета стиля недоступны на тонком клиенте?

Для понимания сути проблемы нам необходимо обратиться к архитектуре клиент-серверного взаимодействия управляемого приложения. Платформа строго разграничивает контексты выполнения кода. Глобальные коллекции оформления интерфейса, такие как ЦветаСтиля, ШрифтыСтиля и РамкиСтиля, по умолчанию инициализируются и живут исключительно на стороне сервера.

Согласно официальной документации (синтакс-помощнику), область доступности для объектов коллекции ЦветаСтиля ограничена следующими контекстами:

В контексте Тонкого клиента и Веб-клиента эти коллекции напрямую недоступны ради экономии сетевого трафика и оперативной памяти клиентского приложения. Попытка прямого обращения к ним приведет к ошибке компиляции клиентского модуля.

Разбор типичного заблуждения: почему не работает ПредопределенноеЗначение()?

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


// Данный код вызовет ошибку!
ЦветКнопки = ПредопределенноеЗначение("ЦветаСтиля.ВажныйЦвет");

Проанализируем, почему этот метод не сработает. Функция ПредопределенноеЗначение() предназначена строго для работы с прикладными объектами метаданных, сохраненными в базе данных. Она поддерживает работу с:

  1. Предопределенными элементами справочников.
  2. Предопределенными элементами планов видов характеристик.
  3. Значениями перечислений.
  4. Точками маршрутов бизнес-процессов.

Системные коллекции оформления (такие как стили оформления) не относятся к перечисленным типам метаданных. Поэтому попытка вызвать данный метод для ЦветаСтиля потерпит неудачу как в тонком, так и в толстом клиенте.

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

Решение 1. Локальное кэширование в реквизитах управляемой формы

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

Разберем этот процесс по шагам:

  1. Добавим в управляемую форму новый реквизит. Назовем его, например, ЦветФонаКнопки. В качестве типа данных укажем системный тип Цвет.
  2. В обработчике события ПриСозданииНаСервере заполним этот реквизит системным цветом стиля.
  3. Используем сохраненное значение на клиенте в нужный момент времени.

Посмотрим на практический пример реализации этого механизма:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Получаем цвет из системной коллекции на сервере и записываем в реквизит формы
    ЦветФонаКнопки = ЦветаСтиля.ПоясняющийТекстОшибки;
    
КонецПроцедуры

&НаКлиенте
Процедура ПриИзмененииДанныхНаКлиенте()
    
    // Безопасно применяем сохраненный цвет на клиенте без вызова сервера
    Элементы.ДекорацияПредупреждение.ЦветТекста = ЦветФонаКнопки;
    
КонецПроцедуры

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

Решение 2. Использование готовых механизмов БСП (Библиотеки стандартных подсистем)

Если вы ведете разработку в типовой конфигурации 1С (такой как УТ, ERP, КА, БП, ЗУП и др.), то в вашем распоряжении уже есть мощный готовый инструмент, встроенный в Библиотеку стандартных подсистем. Разработчики БСП давно решили проблему доступности стилей на клиенте.

Для получения цвета или шрифта стиля на стороне тонкого клиента достаточно вызвать специализированные функции общего модуля:

Пример использования функций БСП в клиентской процедуре:


&НаКлиенте
Процедура ПодкраситьЭлементИнтерфейса()
    
    // Получаем цвет стиля напрямую на клиенте через БСП
    ЦветВыделения = ОбщегоНазначенияКлиент.ЦветСтиля("ЦветОсобогоВыделения");
    Элементы.ПолеВажное.ЦветФона = ЦветВыделения;
    
КонецПроцедуры

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

Решение 3. Реализация собственного механизма кэширования (для самописных конфигураций)

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

Создадим первый общий модуль для извлечения данных с сервера:

  1. Имя модуля: СтилиВызовСервера.
  2. Установим свойства: Сервер = Истина, Вызов сервера = Истина.

Напишем в нем следующий код:


// Функция считывает значение цвета из серверного контекста
Функция ПолучитьЦветСтиляНаСервере(Знач ИмяЦвета) Экспорт
    
    Попытка
        Возврат ЦветаСтиля[ИмяЦвета];
    Исключение
        // Возвращаем пустой цвет в случае ошибочного имени стиля
        Возврат Новый Цвет;
    КонецПопытки;
    
КонецФункции

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

  1. Имя модуля: СтилиКлиентПовтИсп.
  2. Установим свойства: Клиент (управляемое приложение) = Истина.
  3. Установим свойство Повторное использование возвращаемых значений в значение На время сеанса.

Добавим в него функцию, которая будет обращаться к первому серверному модулю:


// Функция кэширует возвращенные цвета на стороне клиента на все время работы сеанса
Функция ЦветСтиля(Знач ИмяЦвета) Экспорт
    
    Возврат СтилиВызовСервера.ПолучитьЦветСтиляНаСервере(ИмяЦвета);
    
КонецФункции

Теперь в любом месте вашей конфигурации на клиенте вы можете написать простую и быструю конструкцию:


&НаКлиенте
Процедура ПрименитьПользовательскиеНастройки()
    
    // Быстрое и безопасное получение цвета с автокэшированием
    Элементы.СписокДокументов.ЦветФона = СтилиКлиентПовтИсп.ЦветСтиля("ФонВажногоДокумента");
    
КонецПроцедуры

Особенности типов данных и мутабельность

При проектировании подобных механизмов важно помнить об особенностях сериализации объектов при переходе границы «клиент-сервер». Некоторые сложные типы данных в 1С являются мутабельными (изменяемыми) и не могут быть переданы с сервера на клиент.

Однако типы данных Цвет и Шрифт в платформе «1С:Предприятие 8» являются немутабельными. Платформа без проблем осуществляет их автоматическую сериализацию в XML/JSON при передаче между контекстами. Это гарантирует надежную работу описанных выше кэширующих схем в любых типах клиентов, включая Веб-клиент под управлением различных интернет-браузеров.

Сводная таблица выбора решений

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

Критерий выбора Локальный реквизит формы Методы БСП Собственный кэш (ПовтИсп)
Сложность реализации Очень низкая (без написания общего кода) Нулевая (вызов готовой функции) Средняя (требуется создать 2 общих модуля)
Область применения Только внутри одной формы Вся конфигурация Вся конфигурация Вся конфигурация
Нагрузка на сервер Однократно при открытии конкретной формы Однократно при первом запросе цвета за сеанс Однократно при первом запросе цвета за сеанс
Зависимость от библиотек Нет Требуется наличие БСП в конфигурации Нет

Таким образом, для простых локальных доработок смело используйте перенос цвета через событие ПриСозданииНаСервере управляемой формы. В крупных корпоративных системах всегда отдавайте предпочтение стандартным механизмам БСП или собственной подсистеме кэширования на модулях с повторным использованием возвращаемых значений.

← На главную