При разработке интерфейсов на управляемых формах часто требуется выделить цветом строки табличной части, удовлетворяющие определенным условиям. В обычном приложении для этого использовались события табличного поля ПриВыводеСтроки или ПриПолученииДанных. В управляемом приложении отрисовка строк полностью делегирована механизму УсловноеОформление. Однако при попытке настроить его программно разработчики часто сталкиваются с тем, что строки не окрашиваются.
Разберем типичные ошибки при программном создании правил условного оформления, выясним причины их возникновения и рассмотрим правильные варианты реализации задачи.
Проанализируем фрагмент кода, с которого обычно начинаются попытки раскрасить строки:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УсОф = ЭтаФорма.УсловноеОформление;
ЭлОформления = УсОф.Элементы.Добавить();
ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Номенклатура.ПринадлежностьФраншизе");
ЭлОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлОтбора.Использование = Истина;
ЭлОтбора.ПравоеЗначение = Перечисления.ПринадлежностьФраншизе.Заказной;
Элемен = ЭлОформления.Оформление.Элементы[1];
Элемен.Использование = Истина;
Элемен.Значение = Новый Цвет(167, 0, 0);
КонецПроцедуры
В приведенном коде скрыты сразу три критические проблемы, из-за которых раскраска не работает:
ЭлОформления.Поля пуста, платформа просто игнорирует созданное правило.ДанныеФормыКоллекция. Это клиентский кэш данных, а не динамический список с прямым запросом к базе данных. Платформа не умеет «разыменовывать» реквизиты ссылок на лету в условном оформлении. Путь вида Объект.Товары.Номенклатура.ПринадлежностьФраншизе работать не будет.Элементы[1] крайне ненадежно: порядок следования параметров оформления в коллекции платформы не фиксирован и зависит от версии платформы или контекста. Вместо цвета фона можно случайно включить признак шрифта или доступности.Рассмотрим наиболее производительный и правильный подход с точки зрения архитектуры платформы. Чтобы платформа могла быстро проверить условие на клиенте без дополнительных запросов к серверу, значение проверяемого реквизита должно непосредственно присутствовать в строке табличной части.
Разберем по шагам, как это реализовать:
ПринадлежностьФраншизе непосредственно в табличную часть документа (или создадим реквизит формы того же типа в ветке Объект.Товары).ТоварыНоменклатураПриИзменении настроим заполнение этого реквизита при выборе номенклатуры.ПриСозданииНаСервере опишем условное оформление с обязательным указанием оформляемых полей.Посмотрим на пример кода в модуле формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создаем элемент условного оформления
ЭлОформления = УсловноеОформление.Элементы.Добавить();
// 1. Указываем оформляемые поля (всю строку таблицы формы)
ПолеЭлемента = ЭлОформления.Поля.Элементы.Добавить();
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.Товары.Имя);
// 2. Настраиваем отбор по прямому реквизиту табличной части
ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.ПринадлежностьФраншизе");
ЭлОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлОтбора.ПравоеЗначение = Перечисления.ПринадлежностьФраншизе.Заказной;
ЭлОтбора.Использование = Истина;
// 3. Устанавливаем параметры оформления по их имени
ЭлОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 200, 200));
КонецПроцедуры
Обратите внимание: чтобы закрасить строку целиком, в ПолеКомпоновкиДанных передается имя элемента таблицы формы (Элементы.Товары.Имя). Если требуется раскрасить только конкретную колонку, в коллекцию Поля добавляется имя поля этой колонки, например Элементы.ТоварыНоменклатура.Имя.
Рассмотрим альтернативную ситуацию: когда нельзя менять структуру метаданных и добавлять новые реквизиты в табличную часть. В этом случае мы можем применить отбор по самой номенклатуре, используя вид сравнения ВСписке.
Однако здесь важно учитывать поведение формы: если заполнить СписокЗначений только в момент открытия документа, новые строки, добавленные пользователем интерактивно, оформляться не будут. Поэтому логику формирования списка необходимо вызывать повторно при редактировании данных.
Посмотрим, как выглядит программная настройка такого оформления:
&НаСервере
Процедура ОбновитьОформлениеТоваровНаСервере()
// Находим или создаем правило оформления
ЭлОформления = Неопределено;
Для Каждого Элемент Из УсловноеОформление.Элементы Цикл
Если Элемент.Представление = "ОформлениеЗаказныхТоваров" Тогда
ЭлОформления = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭлОформления = Неопределено Тогда
ЭлОформления = УсловноеОформление.Элементы.Добавить();
ЭлОформления.Представление = "ОформлениеЗаказныхТоваров";
// Добавляем оформляемое поле
ПолеТаблицы = ЭлОформления.Поля.Элементы.Добавить();
ПолеТаблицы.Поле = Новый ПолеКомпоновкиДанных(Элементы.Товары.Имя);
// Задаем цвет фона
ЭлОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(200, 255, 200));
// Создаем элемент отбора
ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Номенклатура");
ЭлОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлОтбора.Использование = Истина;
Иначе
ЭлОтбора = ЭлОформления.Отбор.Элементы[0];
КонецЕсли;
// Заполняем список номенклатуры, удовлетворяющей условию
СЗНоменклатуры = Новый СписокЗначений;
Для Каждого СтрТЧ Из Объект.Товары Цикл
Если ЗначениеЗаполнено(СтрТЧ.Номенклатура)
И СтрТЧ.Номенклатура.ПринадлежностьФраншизе = Перечисления.ПринадлежностьФраншизе.Заказной Тогда
СЗНоменклатуры.Добавить(СтрТЧ.Номенклатура);
КонецЕсли;
КонецЦикла;
ЭлОтбора.ПравоеЗначение = СЗНоменклатуры;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьОформлениеТоваровНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ОбновитьОформлениеТоваровНаСервере();
КонецПроцедуры
Подведем итог: для корректной работы программного условного оформления в табличных частях всегда обязательно заполняйте коллекцию Поля, используйте метод УстановитьЗначениеПараметра для свойств оформления и помните об ограничении платформы на обращение к полям через точку.