Как правильно присвоить список значений элементу формы и избежать ошибок при отображении?

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

При разработке на платформе 1С:Предприятие 8.3 (особенно в режиме управляемых форм) программисты часто сталкиваются с необходимостью программного ограничения выбора в полях ввода. Типичный сценарий: нужно, чтобы пользователь выбирал значение не из всего справочника, а из заранее подготовленного списка. Однако при попытке реализовать это «в лоб» возникают системные ошибки. В этой статье мы подробно разберем, почему нельзя просто присвоить список значений полю ввода и как правильно обрабатывать данные, чтобы избежать ошибок XDTO-сериализации.

Разбираем ошибку «Поле объекта недоступно для записи»

Начнем с классической ситуации. Программист создает СписокЗначений, наполняет его данными и пытается присвоить его свойству СписокВыбора элемента формы следующим образом:

ЭтаФорма.Элементы.Должность.СписокВыбора = л_СписокДолжностей;

В этот момент система выдает ошибку: «Поле объекта недоступно для записи (СписокВыбора)». Проанализируем причину: свойство СписокВыбора у элемента формы (поля ввода) является коллекцией только для чтения как объект. Это означает, что сам контейнер (объект СписокЗначений) уже создан платформой при инициализации формы, и мы не можем заменить его на другой объект с помощью оператора =.

Правильное решение: вместо попытки перезаписать все свойство, мы должны работать с содержимым уже существующей коллекции. Рассмотрим, как это сделать с помощью метода Загрузить(), который позволяет одним махом заменить все элементы списка на новые:


// л_СписокДолжностей - это наш подготовленный список значений
ЭтаФорма.Элементы.Должность.СписокВыбора.Загрузить(л_СписокДолжностей.ВыгрузитьЗначения());

Или, если у нас есть массив значений, мы можем использовать ЗагрузитьЗначения(). Это полностью очистит текущий список выбора элемента и заполнит его данными из вашего источника.

Проблема отображения типов и XDTO: почему возникает ошибка?

Исправив первую ошибку, разработчики часто наступают на вторые «грабли». При передаче данных между сервером и клиентом возникает ошибка: «Отсутствует отображение для типа 'ЭлементСпискаЗначений'». Это происходит из-за особенностей работы управляемого интерфейса.

Разберем ситуацию подробнее. Когда мы работаем с объектом СписокЗначений, он состоит из объектов типа ЭлементСпискаЗначений. Каждый такой элемент имеет свойства Значение, Представление, Пометка и Картинка. Ошибка возникает тогда, когда в коллекцию, предназначенную для передачи на клиент, попадает сам объект ЭлементСпискаЗначений вместо того значения, которое он несет.

Посмотрим на пример неправильного кода, который приводит к ошибке:


Для Каждого Элемент Из л_СписокДолжностей Цикл
    // ОШИБКА: Попытка добавить в массив сам объект элемента
    л_СписокДолжностей_Массив.Добавить(Элемент); 
КонецЦикла;

Проанализируем причину: платформа 1С не умеет сериализовать (передавать) тип ЭлементСпискаЗначений через XDTO между серверным и клиентским контекстом в данном контексте. Для решения проблемы нам нужно добавлять в список только Значение (например, ссылку на справочник или строку).

Корректный код будет выглядеть так:


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

ЭтаФорма.Элементы.Должность.СписокВыбора.ЗагрузитьЗначения(л_СписокДолжностей_Массив);

Настройка режима работы поля ввода

Просто заполнить список недостаточно, чтобы пользователь увидел удобный выпадающий список. Нам нужно настроить свойства самого элемента формы ПолеВвода. Рассмотрим основные настройки, которые влияют на поведение списка:

  1. РежимВыбораИзСписка (ChoiceListMode): Если установить это свойство в значение Истина, поле ввода превратится в своего рода «комбобокс». Пользователь не сможет вводить произвольный текст или выбирать данные из стандартной формы выбора справочника — он будет ограничен только вашим списком.
  2. КнопкаСпискаВыбора (DropListButton): Обязательно включите это свойство. Оно добавляет маленькую стрелочку в правой части поля, при нажатии на которую выпадает ваш список.
  3. ОграничениеТипа: Если реквизит формы имеет составной тип, рекомендуется явно указать тип данных для поля ввода, чтобы платформа понимала, какие именно ссылки вы предлагаете в списке.

Альтернативный подход: Параметры выбора (ChoiceParameters)

Иногда использование СписокВыбора — это избыточный путь. Если ваша задача заключается в том, чтобы просто отфильтровать элементы справочника по какому-то признаку (например, показывать только активные должности), в 1С есть более изящные механизмы, не требующие написания кода в каждом событии.

Проанализируем альтернативы:

Когда стоит использовать событие «НачалоВыбора»?

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

  1. В обработчике события устанавливаем СтандартнаяОбработка = Ложь. Это отменит открытие стандартной формы справочника.
  2. Программно формируем массив ссылок или список значений.
  3. Открываем форму выбора программно, передавая туда этот массив в качестве параметра Отбор, либо используем метод ВыбратьИзСписка().

Рассмотрим пример использования метода ВыбратьИзСписка, который часто удобнее, чем заполнение свойства элемента:


&НаКлиенте
Процедура ДолжностьНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    Список = ПолучитьСписокДоступныхДолжностейНаСервере();
    
    ВыбранныйЭлемент = ВыбратьИзСписка(Список, Элемент);
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        Объект.Должность = ВыбранныйЭлемент.Значение;
    КонецЕсли;
КонецПроцедуры

Оптимизация и контекст исполнения

Важно помнить, что заполнение списка выбора — это операция, требующая данных с сервера. Если вы будете перезаполнять список при каждом нажатии (например, в событии ПриИзменении другого поля), это может замедлить работу интерфейса из-за постоянных серверных вызовов.

Рекомендация: Если список должностей относительно стабилен, лучше заполнить его один раз при событии ПриСозданииНаСервере. Если же список зависит от другого реквизита, старайтесь минимизировать объем передаваемых данных, передавая только массивы ссылок, а не тяжелые объекты.

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

← На главную