Бодаемся с отображением отборов на управляемых формах

Рассмотрим в статье, как настроить отображение пользовательских отборов на форме по своему желанию.

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

Используя главный инструмент разработчика — а именно метод научного тыка, я определил, что вид сравнения не отображается, если он соответствует виду "Равно". Исправление этой прекрасной находки специалистов по юзабилити из 1С, казалось бы, находится на расстоянии вытянутой руки: вот и заветная галочка, доступная из настроек формы:

 

Казалось бы, дело за малым, перехватить момент, когда отборы попадают на форму, да пройтись по всем элементам группы пользовательских настроек и проставить видимость. 

Итак, первым делом нужно усвоить, что те отборы, которые мы используем через стандартную команду настройки списка, имеют отношение не к самой форме, а к динамическому списку, расположенному на ней, и являются ни чем иным, как пользовательскими настройками. 

Если смотреть свойства динамического списка через палитру, можно найти две зацепки для решения нашей задачи:

1) Во-первых, это свойство "Группа пользовательских настроек". В данном свойстве указывается группа формы, которая выступит родителем для всех добавляемых элементов с отображением отборов.

 

 

2) Во-вторых, это событие списка "ПриОбновленииСоставаПользовательскихНастроекНаСервере".

 

 

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

Рассмотрим программное создание полей на примере рабочего кода:

 

    // Иначе магия не заработает
СтандартнаяОбработка = Ложь;

// Очищаем все созданные элементы с отборами, через удаление главной группы
Для Каждого Эл Из Элементы.СписокКомпоновщикНастроекПользовательскиеНастройки.ПодчиненныеЭлементы Цикл
Элементы.Удалить(Эл);
КонецЦикла;

// Получаем настройки, смотрим количество настроек
Настройки = Список.КомпоновщикНастроек.ПолучитьНастройки();
КоличествоОтборов = Настройки.Отбор.Элементы.Количество();

// Создаём главную группу
ПолеОтборы   = ЭтаФорма.Элементы.Добавить("ПолеОтборы", Тип("ГруппаФормы"), Элементы.СписокКомпоновщикНастроекПользовательскиеНастройки);
ПолеОтборы.Вид  = ВидГруппыФормы.ОбычнаяГруппа;
ПолеОтборы.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
ПолеОтборы.ОтображатьЗаголовок = Ложь;

// Разделяем главную группу на 2 подгруппы, чтобы хватало места всем отборам
ОтборыКолонка1   = ЭтаФорма.Элементы.Добавить("ОтборыКолонка1", Тип("ГруппаФормы"), ПолеОтборы);
ОтборыКолонка1.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ОтборыКолонка1.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
ОтборыКолонка1.ОтображатьЗаголовок  = Ложь;
ОтборыКолонка1.СквозноеВыравнивание = СквозноеВыравнивание.Использовать;

ОтборыКолонка2  = ЭтаФорма.Элементы.Добавить("ОтборыКолонка2", Тип("ГруппаФормы"), ПолеОтборы);
ОтборыКолонка2.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ОтборыКолонка2.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
ОтборыКолонка2.ОтображатьЗаголовок = Ложь;
ОтборыКолонка2.СквозноеВыравнивание = СквозноеВыравнивание.Использовать;

// Разделяем имеющиеся отборы по колонкам, заполнение начнём с первой
НастроекНаКолонку = Окр(КоличествоОтборов/2, 0, РежимОкругления.Окр15как20);
Колонка = ОтборыКолонка1;

// Начинаем добавлять настройки на форму
НомерЭлемента = 0;
Для каждого ЭлОтбора из Настройки.Отбор.Элементы Цикл

//  Проверяем, не пора ли менять колонку
Если НомерЭлемента = НастроекНаКолонку Тогда
Колонка = ОтборыКолонка2;
КонецЕсли;

// Создаём группу под каждую настройку
ПолеГруппыОтбора = ЭтаФорма.Элементы.Добавить("КомпоновщикНастроекПользовательскиеНастройкиЭлемент"+НомерЭлемента, Тип("ГруппаФормы"), Колонка);
ПолеГруппыОтбора.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ПолеГруппыОтбора.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
ПолеГруппыОтбора.ОтображатьЗаголовок = Ложь;
ПолеГруппыОтбора.СквозноеВыравнивание = СквозноеВыравнивание.Использовать;

// Создаём элементы с привязкой к настройкам компоновщика данных
ПолеИспользование = ЭтаФорма.Элементы.Добавить("КомпоновщикНастроекПользовательскиеНастройкиЭлемент"+НомерЭлемента+"Использование", Тип("ПолеФормы"), ПолеГруппыОтбора);
ПолеИспользование.Вид = ВидПоляФормы.ПолеФлажка;
ПолеИспользование.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Лево;
ПолеИспользование.Заголовок = ЭлОтбора.ЛевоеЗначение;
ПолеИспользование.ПутьКДанным = "Список.КомпоновщикНастроек.ПользовательскиеНастройки[0]["+НомерЭлемента+"].Использование";

ПолеВидСравнения = ЭтаФорма.Элементы.Добавить("КомпоновщикНастроекПользовательскиеНастройкиЭлемент"+НомерЭлемента+"ВидСравненияЭлементаОтбора", Тип("ПолеФормы"), ПолеГруппыОтбора);
ПолеВидСравнения.Вид = ВидПоляФормы.ПолеВвода;
ПолеВидСравнения.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ПолеВидСравнения.РастягиватьПоГоризонтали = Ложь;
ПолеВидСравнения.ПутьКДанным = "Список.КомпоновщикНастроек.ПользовательскиеНастройки[0]["+НомерЭлемента+"].ВидСравнения";

ПолеЗначение = ЭтаФорма.Элементы.Добавить("КомпоновщикНастроекПользовательскиеНастройкиЭлемент"+НомерЭлемента+"Значение", Тип("ПолеФормы"), ПолеГруппыОтбора);
ПолеЗначение.Вид = ВидПоляФормы.ПолеВвода;
ПолеЗначение.ВыбиратьТип = Ложь;
ПолеЗначение.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
ПолеЗначение.ПутьКДанным = "Список.КомпоновщикНастроек.ПользовательскиеНастройки[0]["+НомерЭлемента+"].Значение";

НомерЭлемента = НомерЭлемента+1;
КонецЦикла;

 

Как видите, алгоритм не очень сложен, дольше всего я провозился с путём к данным с настройками — первый массив, в который мы попадаем (который жёстко прописан в пути) содержит информацию по отборам, а последующие массивы уже информацию ко конкретным настройкам отбора. 

В итоге мы имеем стройный ряд настроек, который можно поменять в любой момент:

 

14 Comments

  1. Fragster

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

    Расширение таблицы формы для динамического списка (Form table extension for dynamic list)

    СоздатьЭлементыФормыПользовательскихНастроек (CreateUserSettingsFormItems)

    Синтаксис:

    СоздатьЭлементыФормыПользовательскихНастроек(<ГруппаПользовательскихНастроек>, <Режим>, <КоличествоКолонок>)

    Параметры:

    <ГруппаПользовательскихНастроек> (необязательный)

    Тип: ГруппаФормы.

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

    Значение по умолчанию: Неопределено.

    <Режим> (необязательный)

    Тип: РежимОтображенияНастроекКомпоновкиДанных.

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

    Значение по умолчанию: Неопределено.

    <КоличествоКолонок> (необязательный)

    Тип: Число.

    Задает количество колонок, в которых размещаются элементы формы в группе редактирования пользовательских настроек.

    Если параметр не задан, то элементы группы размещаются в двух колонках.

    Описание:

    Создает элементы формы для редактирования пользовательских настроек динамического списка.

    Показать

    Reply
  2. lemz

    (2)

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

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

    Reply
  3. Fragster

    (3) ну, простейшая рекурсивная функция справится с обходом, получается в разы меньше кода. Единственный нюанс — у группы для настроек нужно убрать флажок «Разрешить пользовательское изменение состава группы, РазрешитьИзменениеСостава, EnableContentChange»

    Примерный код такой:

    &НаСервере
    Процедура Реквизит1ПриОбновленииСоставаПользовательскихНастроекНаСерве­ре(СтандартнаяОбработка)
    Элементы.Реквизит1.СоздатьЭлементыФормыПользовательскихНастроек(Элементы.Настройки, , 2);
    УстановитьВидимостьНастроек(Элементы.Настройки);
    КонецПроцедуры
    
    
    &НаСервере
    Процедура УстановитьВидимостьНастроек(ГруппаНастроек)
    Для каждого ПодчиненныйЭлемент Из ГруппаНастроек.ПодчиненныеЭлементы Цикл
    Если ТипЗнч(ПодчиненныйЭлемент) = Тип(«ГруппаФормы») Тогда
    УстановитьВидимостьНастроек(ПодчиненныйЭлемент);
    Иначе
    ПодчиненныйЭлемент.Видимость = Истина;
    КонецЕсли;
    КонецЦикла;
    КонецПроцедуры
    

    Показать

    Reply
  4. Fragster

    (4) Нашел у себя косяк — поскольку видмость устанавливается пользовательскими настройками формы, а мы к ним не имеем прямого доступа, нужно не устанавливать видимость, а все-таки клонировать элементы. Вот рабочий вариант (кода также не очень много):

    &НаСервере
    Процедура УстановитьВидимостьНастроек(ГруппаНастроек)
    МассивКлонируемыхЭлементов = Новый Массив;
    Для каждого ПодчиненныйЭлемент Из ГруппаНастроек.ПодчиненныеЭлементы Цикл
    Если ТипЗнч(ПодчиненныйЭлемент) = Тип(«ГруппаФормы») Тогда
    УстановитьВидимостьНастроек(ПодчиненныйЭлемент);
    Иначе
    Если СтрНайти(ПодчиненныйЭлемент.Имя, «ВидСравнения») <> 0 Тогда
    МассивКлонируемыхЭлементов.Добавить(ПодчиненныйЭлемент);
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    Для каждого КлонируемыйЭлемент Из МассивКлонируемыхЭлементов Цикл
    Клон = ЭтаФорма.Элементы.Вставить(КлонируемыйЭлемент.Имя + «Клон», ТипЗнч(КлонируемыйЭлемент), КлонируемыйЭлемент.Родитель, КлонируемыйЭлемент);
    ЗаполнитьЗначенияСвойств(Клон, КлонируемыйЭлемент, «Вид, ПоложениеЗаголовка, РастягиватьПоГоризонтали, ПутьКДанным»);
    КлонируемыйЭлемент.Видимость = Ложь;
    КонецЦикла;
    КонецПроцедуры

    Показать

    Reply
  5. allgorhythm

    Кручу верчу сравнить хочу!

    Reply
  6. Поручик

    Плохо, что для исправления косяка от 1С, приходится добавлять форму для отчёта на СКД.

    Reply
  7. MorningStalker

    Автору спасибо большое за идею!

    Реализовал у себя, буду теперь использовать.

    Нашел в коде ошибку (видимо осталось от реализации предыдущих вариантов), облегчу реализацию тем, кто воспользуется этим способом:

    ПолеЗначение.ПутьКДанным = «Список.КомпоновщикНастроек.ПользовательскиеНастройки[0][«+НомерЭлемента+»].Значение»;

    это работать не будет, так как в результате получится конструкция Список.КомпоновщикНастроек.ПользовательскиеНастройки[0][0].Значение

    правильно так:

    ПолеЗначение.ПутьКДанным = «Список.КомпоновщикНастроек.ПользовательскиеНастройки[» + НомерЭлемента + «].Значение»;

    Соответственно это справедливо для Использование и ВидСравнения

    Reply
  8. lemz

    (10) Странно что у вас сработал именно такой вариант, так как в моём случае жёстко прописать первый массив пришлось из-за того, что в нём лежит информация по всем отборам, а уже внутри него проходя по номерам мы получаем конкретные значения этих отборов

    Reply
  9. anig99

    Спасибо за указание направления. Написал свой более сложный и универсальный вариант.

    Reply
  10. ward_ed

    Правильно будет определить индекс элемента, следующим образом

    НомерЭлемента = Настройки.Отбор.Элементы.Индекс(ЭлОтбора);.

    Это в том случае если что-то нужно исключить при создании.

    И еще в пользовательские настройки могут попадать и параметры, в данном варианте кода они не выводятся в форму, так как элементы хранятся отдельно.

    Reply
  11. AzagTot

    Автору спасибо за идею!

    Реализовал в точности так, как указано в теме, однако поля отбора недоступны для редактирования. Попробовал для каждого элемента явно указать доступность — все равно та же ситуация. Использование стоит везде. У группы с отборами свойство «Только просмотр» Ложь.

    Ума не приложу, куда еще копать… Может сталкивался кто?

    Платформа 8.3.14, такое же поведение на 8.3.15.

    Reply
  12. AzagTot

    (14) Причина была найдена. Оказывается, если задать предопределенный отбор в конфигураторе и включить ему галочку (включить в пользовательские настройки), то этот отбор сделает недоступными и пользовательские отборы, и сам себя.

    Есть ли возможность полечить это?

    Reply
  13. lemz

    (14) Группой пользовательских настроек для списка у вас выставлен стандартный для форм списка элемент «СписокКомпоновщикНастроекПользовательскиеНастройки»? У него по доступности ничего не залочено?

    Reply
  14. lemz

    (15) Действительно, есть такое. Могу только приметить, что если предопределённый отбор не помечать включенным в пользовательские настройки, в данной реализации он выведется на форму всё равно, при этом ничего не ломая ни со своей доступностью, ни с пользовательскими настройками

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *