Как программно управлять полями и настройками динамического списка?

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

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

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

Почему не работает изменение исполняемой схемы компоновки данных?

Первый инстинктивный порыв — получить исполняемую схему компоновки и поменять что-то в ней. Код может выглядеть так:


// Неправильный подход!
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    СхемаКомпоновкиДанных = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
    // Попытка получить доступ к полям
    ПоляСКД = СхемаКомпоновкиДанных.НаборыДанных.НаборДанныхДинамическогоСписка.Поля;
    // Здесь ПоляСКД.Количество() будет равно 0
КонецПроцедуры

Этот подход не работает по двум причинам:

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

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

Правильный подход: работа напрямую с объектом динамического списка

Все необходимые инструменты для управления списком находятся в самом реквизите формы типа ДинамическийСписок. Рассмотрим два основных сценария.

Решение 1: Динамическое добавление поля в запрос и на форму

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

Шаг 1. Модифицируем текст запроса.

В обработчике ПриСозданииНаСервере получаем доступ к свойству ТекстЗапроса и изменяем его. Чтобы не переписывать весь запрос и сделать код более универсальным, можно аккуратно встроить новое поле в список выборки.

Посмотрим на пример. Добавим поле ДоговорКонтрагента в список документов реализации.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
    // Разделяем список выбираемых полей по запятой
    ЧастиЗапроса = СтрРазделить(Список.ТекстЗапроса, ",");
	
    // Вставляем наше новое поле (например, вторым по счету)
    ЧастиЗапроса.Вставить(1, "
    |ДокументРеализацияТоваровУслуг.ДоговорКонтрагента КАК ДоговорКонтрагента");
	
    // Собираем текст запроса обратно
    Список.ТекстЗапроса = СтрСоединить(ЧастиЗапроса, ",");
	
    // ... дальнейшие действия
	
КонецПроцедуры

После того как свойство ТекстЗапроса будет изменено, платформа автоматически перестроит внутренние структуры динамического списка, и новое поле станет доступно в его данных.

Шаг 2. Добавляем колонку на форму.

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

Продолжим наш пример:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
    // ... код изменения текста запроса из Шага 1 ...
	
    // Создаем новый элемент формы типа ПолеФормы
    // Вставляем его в группу элементов списка (Элементы.Список)
    // перед элементом "СуммаДокумента"
    НовыйЭлемент = Элементы.Вставить("СписокДоговорКонтрагента", Тип("ПолеФормы"), Элементы.Список, Элементы.СуммаДокумента);
    НовыйЭлемент.Вид = ВидПоляФормы.ПолеНадписи;	  
    
    // Устанавливаем связь с данными. Путь должен быть "ИмяСписка.ИмяПоля"
    НовыйЭлемент.ПутьКДанным = "Список.ДоговорКонтрагента";
	
КонецПроцедуры

Решение 2: Управление свойствами уже существующих полей

Рассмотрим исходную задачу автора: программно изменить свойство поля, например ВыражениеПредставления. Это свойство, появившееся в платформе 8.3.20, позволяет задать на языке выражений СКД, как именно будет отображаться значение поля, не меняя при этом само значение.

Для этого нужно обратиться к коллекции Поля самого динамического списка. После того как ТекстЗапроса установлен (в конфигураторе или программно), эта коллекция будет заполнена.

Пример: Добавим к наименованию номенклатуры ее артикул.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Находим нужное поле в коллекции полей динамического списка
    ПолеНоменклатура = Список.Поля.Найти("Номенклатура");
    
    Если ПолеНоменклатура <> Неопределено Тогда
        // Устанавливаем выражение для представления
        // Используем язык выражений системы компоновки данных
        ПолеНоменклатура.ВыражениеПредставления = 
            "ВЫБОР 
            |    КОГДА Номенклатура.Артикул <> """" 
            |    ТОГДА Номенклатура.Наименование + "" (арт. "" + Номенклатура.Артикул + "")"" 
            |    ИНАЧЕ Номенклатура.Наименование 
            |КОНЕЦ";
            
        // Также можно изменить заголовок
        ПолеНоменклатура.Заголовок = "Товар (с артикулом)";
    КонецЕсли;
    
КонецПроцедуры

Важный момент: если вы программно формируете текст запроса, этот код нужно выполнять после того, как вы присвоили новое значение свойству Список.ТекстЗапроса.

Что делать, если коллекция Список.Поля пуста?

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

В этом случае можно попробовать использовать более поздние серверные события формы, например:

Эти события вызываются после создания формы и загрузки основных настроек, что повышает вероятность того, что динамический список уже будет полностью инициализирован. Однако в большинстве случаев достаточно корректно выстроить код внутри ПриСозданииНаСервере: сначала все манипуляции с ТекстЗапроса, и только потом — работа с коллекцией Поля.

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

← На главную