При работе с управляемыми формами в 1С:Предприятии 8 разработчики часто сталкиваются с необходимостью программно управлять отборами динамических списков. Одна из типичных задач — сделать так, чтобы программно созданный отбор не просто тихо отрабатывал в фоне, а отображался на форме в пользовательских настройках (в так называемой «шапке» списка или в окне настройки «Еще -> Настроить список»).
В интерактивном режиме для этого достаточно зайти в свойства элемента отбора и установить флаг «Включать в пользовательские настройки». Однако при попытке сделать это программно разработчики часто заходят в тупик. Давайте подробно разберем, почему возникает эта сложность, как устроен механизм связи основных и пользовательских настроек компоновщика данных, и как решить эту задачу правильно.
Первое интуитивное желание программиста 1С — обратиться напрямую к коллекции пользовательских настроек формы и добавить элемент туда. Выглядит это примерно так:
// Попытка прямого добавления элемента в пользовательские настройки
ЭлементОтбора = Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
При выполнении такого кода платформа незамедлительно вызовет ошибку: «Коллекция пользовательских настроек не может изменять свой состав, так как она связана с настройками компоновки данных».
Дело в том, что объект ПользовательскиеНастройки (тип ПользовательскиеНастройкиКомпоновкиДанных) — это не самостоятельная коллекция. Она является своеобразной «проекцией» основных настроек компоновщика. Платформа самостоятельно управляет составом этой коллекции на основе связей, описанных в основных настройках компоновщика (КомпоновщикНастроек.Настройки). Напрямую добавлять или удалять элементы из этой коллекции нельзя. Единственный способ заставить платформу поместить отбор в пользовательские настройки — это связать элемент основного отбора со структурой пользовательских настроек.
Чтобы элемент отбора стал доступен пользователю (то есть у него программно установился флаг «Включать в пользовательские настройки»), ему необходимо присвоить уникальный идентификатор. Связующим звеном между основным отбором и пользовательскими настройками выступает свойство ИдентификаторПользовательскойНастройки элемента отбора.
Как только мы генерируем и записываем в это свойство новый УникальныйИдентификатор, платформа автоматически понимает, что данный элемент нужно спроецировать в коллекцию пользовательских настроек. С этого момента флаг «Включать в пользовательские настройки» для этого элемента считается установленным.
Рассмотрим практическую задачу. Нам нужно программно добавить отбор по полю «Округ» в динамический список на форме, включить этот отбор в пользовательские настройки и вывести его непосредственно на форму в область быстрого доступа (шапку списка).
Реализуем этот алгоритм по шагам на стороне сервера (например, в обработчике события ПриСозданииНаСервере):
&НаСервере
Процедура УстановитьОтборОкругаНаСервере()
// 1. Получаем коллекцию элементов основного отбора компоновщика настроек динамического списка
КоллекцияОтбора = Список.КомпоновщикНастроек.Настройки.Отбор;
// Очищаем существующие элементы, если требуется полная перезапись отборов
КоллекцияОтбора.Элементы.Очистить();
// 2. Создаем новый элемент отбора в основных настройках
НовыйЭлемент = КоллекцияОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Округ");
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.Использование = Истина;
НовыйЭлемент.ПравоеЗначение = Справочники.Округа.ПустаяСсылка(); // или конкретное значение
// 3. Устанавливаем режим отображения.
// БыстрыйДоступ выведет элемент непосредственно на форму над списком.
НовыйЭлемент.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
// 4. Главный секрет: присваиваем уникальный идентификатор!
// Именно эта строка включает флаг "Включать в пользовательские настройки"
НовыйЭлемент.ИдентификаторПользовательскойНастройки = Строка(Новый УникальныйИдентификатор());
КонецПроцедуры
Проанализируем этот код подробнее. После выполнения строки с генерацией УникальныйИдентификатор платформа сама создаст связанный элемент в Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы. Пользователь сразу же увидит поле отбора на форме и сможет управлять его значением.
При программной настройке крайне важно управлять свойством РежимОтображения элемента настройки. Платформа 1С предлагает три режима из системного перечисления РежимОтображенияЭлементаНастройкиКомпоновкиДанных:
БыстрыйДоступ — элемент отбора отображается непосредственно на форме (обычно в шапке динамического списка). Это наиболее удобный вариант для часто используемых фильтров (например, период, организация, статус документа).Обычный — отбор не выносится на форму, но пользователь может найти его и изменить, зайдя в меню «Еще -> Настроить список...» на вкладку «Отбор».Недоступный — отбор накладывается программно, работает в фоне, но полностью скрыт от глаз пользователя. Пользователь не сможет его увидеть, изменить или отключить.Если элемент отбора уже создан и выведен в пользовательские настройки, изменять его значение в коде (например, при выборе значения в другом поле формы) нужно уже через коллекцию ПользовательскиеНастройки. Прямое изменение в основных настройках может не обновить интерфейс формы.
Правильный алгоритм изменения значения выглядит следующим образом:
ИдентификаторПользовательскойНастройки.ПользовательскиеНастройки.Рассмотрим пример реализации:
&НаСервере
Процедура ИзменитьЗначениеОтбораНаСервере(ИмяПоля, НовоеЗначение)
ИдентификаторНастройки = "";
// Шаг 1. Ищем элемент в основных настройках
Для Каждого ЭлементИзНастроек Из Список.КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если ТипЗв(ЭлементИзНастроек) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если ЭлементИзНастроек.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля) Тогда
ИдентификаторНастройки = ЭлементИзНастроек.ИдентификаторПользовательскойНастройки;
Прервать;
EndЕсли;
КонецЕсли;
КонецЦикла;
// Шаг 2. Если нашли идентификатор, меняем значение в пользовательских настройках
Если ЗначениеЗаполнено(ИдентификаторНастройки) Тогда
ПользовательскийЭлемент = Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторНастройки);
Если ПользовательскийЭлемент <> Неопределено Тогда
ПользовательскийЭлемент.ПравоеЗначение = НовоеЗначение;
ПользовательскийЭлемент.Использование = ЗначениеЗаполнено(НовоеЗначение);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если ваша конфигурация разработана на платформе 1С с использованием Библиотеки Стандартных Подсистем (БСП), вам не обязательно писать весь этот громоздкий код вручную. В БСП есть отличный программный интерфейс, который инкапсулирует всю работу по генерации уникальных идентификаторов и настройке отображения элементов.
Для быстрой установки отборов в динамических списках рекомендуется использовать готовую процедуру общего модуля:
// Пример использования БСП для установки отбора в пользовательских настройках
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"Округ",
Округ,
ВидСравненияКомпоновкиДанных.Равно,
"Округ",
Истина,
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ
);
Эта функция самостоятельно проверит, существует ли уже отбор по данному полю. Если отбор существует — она обновит его значение. Если нет — создаст новый, автоматически присвоит ему UUID (что эквивалентно установке флага «Включать в пользовательские настройки») и выведет его на форму в режиме быстрого доступа. Для реализации сложных фильтраций без кодирования можно использовать расширение для настройки дополнительных отборов в списках на базе БСП.
Иногда при динамическом изменении настроек компоновщика на клиенте (например, по нажатию кнопки на форме) новые элементы быстрого доступа могут не сразу отобразиться в интерфейсе пользователя. Чтобы гарантированно перерисовать панель пользовательских настроек на форме, используйте метод формы:
// Принудительное обновление отображения пользовательских настроек на управляемой форме
Элементы.Список.СоздатьЭлементыФормыПользовательскихНастроек(РежимОтображенияНастроекКомпоновкиДанных.Все);
Этот метод заставляет платформу перечитать текущее состояние коллекции ПользовательскиеНастройки динамического списка и заново отрисовать все визуальные элементы управления на форме.
Применяя эти простые правила и понимая взаимосвязь между основными настройками компоновщика и пользовательскими проекциями, вы сможете легко и безошибочно управлять любыми сложными фильтрами динамических списков прямо из кода вашей конфигурации.