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