Почему заполненный программно список выбора не отображается на форме 1С:Предприятие 8.3?

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

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

Понимание механизма работы событий выбора и СписокВыбора

В 1С:Предприятие 8.3 с управляемыми формами существует несколько важных событий и объектов, которые определяют поведение поля ввода со списком выбора (а для глубокого анализа связей объектов пригодится Analyzer 1C). Мы рассмотрим основные из них.

  1. События НачалоВыбора и НачалоВыбораИзСписка

    В более старых версиях платформы или для полей, где список выбора формировался по специфическим правилам, активно использовалось событие НачалоВыбораИзСписка. Однако в современных версиях 1С:Предприятие 8.3 и выше это событие для полей ввода может не вызываться. Платформа предпочитает автоматически формировать и выводить выпадающий список, если это возможно.

    Основное событие, на которое мы должны ориентироваться для программного заполнения списка при нажатии на кнопку выбора или по F4, — это НачалоВыбора.

    Важно: В обработчике события НачалоВыбора существуют ограничения на вызовы серверных методов. Синтакс-помощник явно указывает: "В обработчике данного события нельзя использовать серверные методы формы с директивой компиляции &НаСервере, а также изменять свойства, которые могут привести к серверному вызову." Это означает, что если вам необходимо получить данные с сервера для заполнения списка, это нужно сделать заранее или использовать методы с директивой &НаСервереБезКонтекста, но и они, как показывает практика, не всегда решают проблему именно с отображением списка, если проблема глубже. В большинстве случаев сам объект СписокВыбора заполняется на клиенте, но данные для него могут быть получены с сервера.

  2. Объект СписокВыбора

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

    • Значение: Это то, что будет фактически возвращено и установлено в реквизит формы после выбора пользователя.
    • Представление: Это текст, который пользователь увидит в выпадающем списке.

    Если мы используем метод ЗагрузитьЗначения(Массив), как в примере Элементы.Расходная.СписокВыбора.ЗагрузитьЗначения(МассивНакладных);, платформа обычно пытается автоматически определить Представление для каждого элемента массива (например, для ссылок на документы это будет их стандартное представление). Однако, если массив содержит сложные объекты, объекты с пустым представлением или по какой-то причине платформа не может корректно сформировать представление, список может отображаться пустым или некорректно.

Проверка основных настроек поля ввода

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

  1. Свойство "Режим выбора из списка"

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

    Давайте проверим это свойство для нашего поля.

  2. Привязка обработчика события

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

Правильное заполнение СписокВыбора

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

  1. Явное указание Значения и Представления

    Хотя метод ЗагрузитьЗначения(Массив) удобен, иногда он может работать не так, как ожидается, особенно если в массиве содержатся ссылки на объекты, у которых нет стандартного представления или оно пустое.

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

    Рассмотрим пример, как это можно сделать:

    
    &НаКлиенте
    Процедура РасходнаяНачалоВыбора(Элемент, СтандартнаяОбработка)
        СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку выбора
            
        Элемент.СписокВыбора.Очистить(); // Очищаем список перед заполнением
            
        // Допустим, МассивНакладныхПолученРанее - это массив ссылок на документы
        // Если данные нужно получать с сервера, их нужно запросить заранее
        // или использовать &НаСервереБезКонтекста для получения, но не для заполнения списка
        МассивНакладных = ПолучитьНакладныеДляВыбораНаСервереБезКонтекста(); 
                
        Для Каждого НакладнаяСсылка Из МассивНакладных Цикл
            // Здесь мы явно указываем Значение (ссылку) и Представление (например, номер и дату)
            Элемент.СписокВыбора.Добавить(НакладнаяСсылка, Строка(НакладнаяСсылка) + " от " + Формат(НакладнаяСсылка.Дата, "ДФ=dd.MM.yyyy"));
        КонецЦикла;
    КонецПроцедуры
            
    &НаСервереБезКонтекста
    Функция ПолучитьНакладныеДляВыбораНаСервереБезКонтекста()
        МассивНакладных = Новый Массив;
        Запрос = Новый Запрос;
        Запрос.Текст = 
        "ВЫБРАТЬ
        |    РасходнаяНакладная.Ссылка
        |ИЗ
        |    Документ.РасходнаяНакладная КАК РасходнаяНакладная
        |ГДЕ
        |    НЕ РасходнаяНакладная.ПометкаУдаления
        |    И РасходнаяНакладная.Проведен"; // Пример алгоритма выбора
                
        Выборка = Запрос.Выполнить().Выбрать();
        Пока Выборка.Следующий() Цикл
            МассивНакладных.Добавить(Выборка.Ссылка);
        КонецЦикла;
        Возврат МассивНакладных;
    КонецФункции
    

    В этом примере мы используем явное добавление элементов через метод Добавить(). Это дает нам полный контроль над тем, что будет показано пользователю.

  2. Проверка содержимого массива

    Убедитесь, что МассивНакладных действительно содержит те значения, которые вы ожидаете. Если массив пуст или содержит некорректные ссылки, то и СписокВыбора будет выглядеть пустым или некорректным.

Установка СтандартнаяОбработка = Ложь

В событии НачалоВыбора установка параметра СтандартнаяОбработка = Ложь; является критически важной. Этот оператор сообщает платформе, что мы хотим отменить ее стандартное действие по выбору (например, открытие формы выбора документа) и вместо этого использовать наш программно заполненный СписокВыбора.

Если вы не установите СтандартнаяОбработка = Ложь, платформа, скорее всего, проигнорирует ваш заполненный СписокВыбора и попытается открыть стандартную форму выбора.

Однако, как было отмечено в обсуждении, иногда даже с СтандартнаяОбработка = Ложь список может не отображаться. Это может быть связано с более фундаментальными проблемами, такими как неправильная настройка свойства "Режим выбора из списка" или некорректное заполнение Представления.

Размещение кода заполнения списка выбора

Время и место вызова кода для заполнения СписокВыбора имеют большое значение.

  1. ПриСозданииНаСервере

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

    
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        // ... другие инициализации формы
                
        // Получаем данные для списка выбора
        МассивНакладных = ПолучитьНакладныеДляВыбораНаСервере();
                
        // Заполняем список выбора для элемента формы
        // Предполагаем, что элемент формы называется "ПолеРасходнаяНакладная"
        Элементы.ПолеРасходнаяНакладная.СписокВыбора.Очистить();
        Для Каждого НакладнаяСсылка Из МассивНакладных Цикл
            Элементы.ПолеРасходнаяНакладная.СписокВыбора.Добавить(НакладнаяСсылка, Строка(НакладнаяСсылка) + " от " + Формат(НакладнаяСсылка.Дата, "ДФ=dd.MM.yyyy"));
        КонецЦиклов;
    КонецПроцедуры
    
  2. ПриИзменении других полей

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

    
    &НаКлиенте
    Процедура КонтрагентПриИзменении(Элемент)
        // При изменении контрагента переформировываем список накладных
        ОбновитьСписокНакладных();
    КонецПроцедуры
            
    &НаКлиенте
    Процедура ОбновитьСписокНакладных()
        // Предполагаем, что Контрагент - это реквизит формы
        Если ЗначениеЗаполнено(Объект.Контрагент) Тогда
            МассивНакладных = ПолучитьНакладныеДляВыбораПоКонтрагентуНаСервере(Объект.Контрагент);
        Иначе
            МассивНакладных = Новый Массив; // Если контрагент не выбран, список пуст
        КонецЕсли;
                
        Элементы.ПолеРасходнаяНакладная.СписокВыбора.Очистить();
        Для Каждого НакладнаяСсылка Из МассивНакладных Цикл
            Элементы.ПолеРасходнаяНакладная.СписокВыбора.Добавить(НакладнаяСсылка, Строка(НакладнаяСсылка) + " от " + Формат(НакладнаяСсылка.Дата, "ДФ=dd.MM.yyyy"));
        КонецЦикла;
    КонецПроцедуры
            
    &НаСервереБезКонтекста
    Функция ПолучитьНакладныеДляВыбораПоКонтрагентуНаСервере(Контрагент)
        // ... логика получения накладных с сервера по контрагенту
    КонецФункции
    
  3. Почему НачалоВыбора может быть "слишком поздно"

    Хотя НачалоВыбора — правильное событие для заполнения списка, который должен отобразиться при нажатии на кнопку выбора, иногда пользователи ожидают увидеть уже заполненный список при первом открытии формы или при наведении на поле. Если список заполняется только в НачалоВыбора, он будет пуст до первого взаимодействия пользователя. Для "предварительной" загрузки списка лучше использовать ПриСозданииНаСервере.

Альтернативные методы для динамического выбора

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

  1. Использование метода ПоказатьВыборИзСписка()

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

    Разберем пример его использования:

    
    &НаКлиенте
    Процедура РасходнаяНачалоВыбора(Элемент, СтандартнаяОбработка)
        СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
            
        СписокДляВыбора = Новый СписокЗначений;
        // Здесь мы заполняем СписокЗначений, например, из полученного ранее массива
        // ... (получение МассиваНакладных, как в предыдущих примерах)
        МассивНакладных = ПолучитьНакладныеДляВыбораНаСервереБезКонтекста();
                
        Для Каждого НакладнаяСсылка Из МассивНакладных Цикл
            // Элементы СписокЗначений также имеют Значение и Представление
            СписокДляВыбора.Добавить(НакладнаяСсылка, Строка(НакладнаяСсылка) + " от " + Формат(НакладнаяСсылка.Дата, "ДФ=dd.MM.yyyy"));
        КонецЦикла;
                
        // Создаем описание оповещения для обработки выбора пользователя
        ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьВыборНакладной", ЭтотОбъект);
                
        // Открываем список для выбора
        Элемент.ПоказатьВыборИзСписка(ОписаниеОповещения, СписокДляВыбора);
    КонецПроцедуры
            
    &НаКлиенте
    Процедура ОбработатьВыборНакладной(ВыбранноеЗначение, ДополнительныеПараметры) Экспорт
        Если ВыбранноеЗначение <> Неопределено Тогда
            // Устанавливаем выбранное значение в реквизит формы
            Объект.Расходная = ВыбранноеЗначение;
        КонецЕсли;
    КонецПроцедуры
    

    При использовании ПоказатьВыборИзСписка() нам нужно передать сам список значений и ОписаниеОповещения, которое указывает, какой метод и в каком объекте будет вызван после того, как пользователь сделает выбор.

  2. Открытие формы выбора с отбором

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

    Разберем, как это реализовать:

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

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

Итоги и рекомендации по устранению проблемы

Чтобы решить проблему с неотображаемым списком выбора, мы рекомендуем последовательно выполнить следующие шаги:

  1. Проверить свойство "Режим выбора из списка": Убедитесь, что оно установлено в Истина для вашего поля ввода. Это базовая, но очень частая причина.
  2. Установить СтандартнаяОбработка = Ложь: В обработчике события НачалоВыбора обязательно пропишите эту строку.
  3. Явно заполнить Значение и Представление: Если вы используете ЗагрузитьЗначения(Массив) и список пуст, попробуйте явно добавлять элементы в СписокВыбора, указывая и Значение, и Представление для каждого элемента.
  4. Перенести заполнение списка: Если список должен быть доступен сразу при открытии формы, заполняйте его в ПриСозданииНаСервере. Если список зависит от других полей, используйте ПриИзменении этих полей для его обновления. НачалоВыбора используйте для непосредственной демонстрации списка при клике.
  5. Проверить логику получения данных: Убедитесь, что ваш массив накладных (или других объектов) действительно содержит ожидаемые данные и не пуст.
  6. Использовать альтернативные методы: Если все вышеперечисленное не помогает, рассмотрите применение ПоказатьВыборИзСписка() или открытие формы выбора с отбором.

Помните, что детальный анализ и проверка каждого из этих пунктов помогут вам локализовать и устранить проблему с отображением программно заполненного списка выбора в 1С:Предприятие 8.3.

← На главную