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