В разработке на платформе 1С:Предприятие 8.3 часто возникает задача визуального выделения строк в списках. Одной из наиболее сложных вариаций этой задачи является ситуация, когда цвет строки не предопределен заранее, а хранится непосредственно в объекте базы данных, например, в реквизите с типом ХранилищеЗначений. Рассмотрим детально, как реализовать такую раскраску в управляемой форме списка, учитывая особенности производительности и ограничения платформы разных версий.
Основная сложность заключается в том, что Динамический список работает на основе SQL-запросов, которые эффективно извлекают примитивные типы данных (числа, строки, даты). Однако реквизит типа ХранилищеЗначений содержит бинарные данные. Платформа не может «на лету» десериализовать цвет из хранилища непосредственно в запросе, чтобы применить стандартное УсловноеОформление. Проанализируем, как обойти это ограничение.
Начиная с версии платформы 8.3.10, для динамических списков стал доступен мощный инструмент — событие ПриПолученииДанныхНаСервере. Рассмотрим этот механизм подробнее. Этот обработчик вызывается после того, как сервер подготовил порцию данных для отображения на клиенте, но до того, как они были отправлены в форму.
Разберем по шагам реализацию в модуле формы списка:
ПриПолученииДанныхНаСервере.ОформленияСтрок. Это коллекция, в которой содержатся данные строк, подготовленных к выводу.Пример кода для реализации этой логики:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Перебираем строки, которые платформа подготовила для вывода на экран
Для Каждого СтрокаСписок Из Строки Цикл
// Получаем ссылку на текущий элемент справочника
ТекущаяСсылка = СтрокаСписок.Ключ;
// ВНИМАНИЕ: Прямое чтение объекта в цикле снижает производительность.
// Рекомендуется кэшировать данные или использовать вспомогательные реквизиты.
ОбъектДанных = ТекущаяСсылка.ПолучитьОбъект();
Если ТипЗнч(ОбъектДанных.Цвет) = Тип("ХранилищеЗначений") Тогда
ЗначениеЦвета = ОбъектДанных.Цвет.Получить();
Если ТипЗнч(ЗначениеЦвета) = Тип("Цвет") Тогда
// Устанавливаем цвет фона для всей строки
СтрокаСписок.Значение.Оформление["Код"].УстановитьЗначениеПараметра("ЦветФона", ЗначениеЦвета);
// Если нужно раскрасить всю строку, используем цикл по полям или конкретное поле
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Метод, описанный выше (с получением объекта через ПолучитьОбъект()), крайне непроизводителен. Выясним причину: при прокрутке списка для каждой строки сервер будет выполнять отдельный запрос к базе данных для десериализации ХранилищаЗначений. Это приведет к «тормозам» интерфейса.
Рассмотрим правильный архитектурный подход:
ЦветЧислом (тип Число).ПередЗаписью) будем извлекать цвет из хранилища и сохранять его числовое представление (RGB).Посмотрим на пример преобразования цвета в число:
// В модуле объекта
Процедура ПередЗаписью(Отказ)
Если ТипЗнч(Цвет) = Тип("ХранилищеЗначений") Тогда
ЗначениеЦвета = Цвет.Получить();
Если ТипЗнч(ЗначениеЦвета) = Тип("Цвет") Тогда
// Сохраняем компоненты цвета для быстрого доступа
ЭтотОбъект.ЦветЧислом = (ЗначениеЦвета.Красный * 65536) + (ЗначениеЦвета.Зеленый * 256) + ЗначениеЦвета.Синий;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выясним, как использовать подход с «маркерами», упомянутый опытными разработчиками. Если количество цветов ограничено (например, 10–20 вариантов), лучше использовать Условное Оформление формы.
Проанализируем ситуацию: вместо передачи самого объекта цвета, мы передаем строковый или числовой код. В настройках списка в конфигураторе или программно создаем правила: «Если Поле КодЦвета равно 1, тогда ЦветФона — Красный». Это работает быстрее всего, так как отрисовка ложится на платформенные механизмы, оптимизированные под работу с видеокартой.
При работе в версии 8.3.12 вы столкнетесь с проблемой: активная (выделенная курсором) строка перекрывает вашу раскраску системным синим цветом. Пользователь не увидит цвет фона, пока не перейдет на другую строку.
Начиная с версии 8.3.13, разработчики 1С добавили свойство ЦветФонаВыделения. Рассмотрим, как это помогает нам: мы можем установить цвет выделения в значение Авто или настроить его так, чтобы он был полупрозрачным, позволяя видеть основной цвет строки. В 8.3.12, как отмечалось в обсуждении, выделенной строке «все равно» на программную раскраску фона, поэтому рекомендуется раскрашивать не всю строку, а конкретную колонку (например, Код или специально созданную колонку-индикатор).
Для достижения наилучшего результата выполним следующие действия:
ХранилищаЗначений напрямую в форме списка.ПриПолученииДанныхНаСервере, обращаемся к коллекции Строки, которая минимизирует количество обращений к БД.Такой подход обеспечит быструю работу интерфейса и корректное отображение визуальной информации даже в крупных справочниках.