При разработке интерфейсов для обычных форм в 1С часто возникает задача реализации удобного автоподбора или "type-ahead" функционала в полях ввода. Пользователи хотят начать вводить текст, и чтобы по мере ввода под полем появлялся динамически уточняющийся выпадающий список вариантов, при этом без необходимости переключать фокус на этот список. Стандартные механизмы платформы на обычных формах, как мы далее выясним, имеют ограничения, которые усложняют достижение этой цели. Рассмотрим подробно, как мы можем подойти к решению этой проблемы.
Прежде чем погрузиться в решения, давайте проанализируем, почему стандартные подходы 1С на обычных формах не удовлетворяют нашему ключевому требованию – сохранению фокуса в поле ввода.
Мы знаем, что для полей ввода в 1С существуют методы, которые позволяют показать список выбора или предложить варианты для автоподбора. Например, метод ВыбратьИзСписка() предназначен для открытия списка выбора. Однако, как мы видим, когда мы вызываем этот метод, фокус ввода автоматически перемещается в открывшийся список. Это стандартное поведение платформы, и оно не позволяет пользователю продолжать ввод текста в исходное поле, пока открыт список.
Аналогично, свойство "Автоподбор" и метод УстановитьВозможныеЗначения(), которые можно использовать в обработчиках событий поля ввода, таких как ПриИзменении или ПриВводеТекста, также сопряжены с перемещением фокуса. Хотя они позволяют динамически обновлять список предлагаемых значений по мере ввода, они не решают проблему сохранения фокуса. Платформа 1С на обычных формах, в отличие от управляемых форм, предоставляет меньше возможностей для низкоуровневого управления элементами интерфейса, обработкой произвольных нажатий кнопок или детальным контролем над фокусом ввода. Это является корневой причиной, почему "из коробки" такая функциональность не работает так, как мы хотим.
Поскольку встроенные механизмы платформы на обычных формах не дают нам необходимого контроля над фокусом, наиболее надежным и гибким решением для реализации полноценного автоподбора с сохранением фокуса является использование Внешних компонент (ВК).
Внешние компоненты – это специальные библиотеки, обычно разрабатываемые на других языках программирования (например, C++, C#, Delphi), которые могут быть подключены к системе 1С. Они позволяют обойти ограничения платформы 1С в части работы с интерфейсом, предоставляя более низкоуровневый доступ к событиям ввода, управлению фокусом и отображению кастомных элементов.
Что именно дают нам ВК в данном случае?
Разработка собственной внешней компоненты требует специфических навыков программирования на языках, поддерживающих создание COM-объектов или нативных библиотек. Однако, как мы видим, для решения этой проблемы уже существуют готовые наработки и статьи, в том числе на специализированных ресурсах, таких как Инфостарт. Эти готовые решения часто предоставляют ActiveX-контролы, которые можно легко встроить в обычные формы 1С и использовать их для создания собственного механизма автоподбора.
Помимо внешних компонент, существуют и другие, менее идеальные или более ограниченные подходы, которые мы можем рассмотреть, хотя они не всегда полностью удовлетворяют требованию сохранения фокуса или привносят другие сложности.
Ранее мы упомянули метод УстановитьВозможныеЗначения(). Хотя он позволяет динамически обновлять список предложений, он всегда перемещает фокус в этот список. Поэтому, если ваше требование к сохранению фокуса является критическим, этот метод не подойдет. Однако, если частичная потеря фокуса приемлема (например, пользователь должен сначала выбрать из списка, а потом продолжить ввод), этот метод может быть рассмотрен как более простая альтернатива.
Еще один подход, который обсуждался для обычных форм и при котором фокус ввода не теряется с основного поля, – это динамическое создание элемента формы типа "ПолеСписка". Мы можем создать этот элемент программно, позиционировать его относительно нашего поля ввода и заполнять его данными по мере ввода текста.
ПолеСписка.
ПриВводеТекста нашего основного поля ввода мы получаем введенный текст.
ПолеСписка полученными данными.
ПолеСписка так, чтобы он выглядел как выпадающий список под нашим полем ввода.
Однако, при использовании такого подхода мы сталкиваемся с рядом сложностей:
ПолеСписка может не обладать всем необходимым функционалом для удобной работы пользователя, например, автоматической прокруткой к выделенному элементу по мере ввода.
Таким образом, хотя динамическое создание ПолеСписка позволяет сохранить фокус, оно требует значительных усилий по реализации и поддержке его поведения, и в конечном итоге может оказаться менее гибким и стабильным, чем использование внешней компоненты.
Давайте рассмотрим шаги, которые нам предстоит выполнить для реализации автоподбора через внешнюю компоненту, сохраняя фокус в поле ввода. Предположим, мы уже имеем или разработали внешнюю компоненту, способную отображать кастомные всплывающие списки и перехватывать события.
Вначале мы подключаем нашу внешнюю компоненту к форме. Это обычно делается в модуле формы при её открытии. Мы создаем экземпляр объекта ВК и связываем его с нашим полем ввода.
Нам нужно настроить внешнюю компоненту или стандартный обработчик ПриВводеТекста нашего поля таким образом, чтобы при каждом изменении текста (или после ввода трех символов) запускалась наша логика. ВК позволяет более тонко перехватывать события нажатия клавиш, что дает больше контроля.
Когда количество введенных символов достигает заданного порога (например, 3 символа), мы формируем список возможных значений. Это обычно делается путем выполнения запроса к информационной базе, фильтруя данные по введенному тексту. Например, если мы ищем номенклатуру, мы будем искать по наименованию, артикулу и т.д.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &ВведенныйТекст
| ИЛИ Номенклатура.Артикул ПОДОБНО &ВведенныйТекст";
Запрос.УстановитьПараметр("ВведенныйТекст", "%" + ПолеВвода.Текст + "%");
Выборка = Запрос.Выполнить().Выбрать();
СписокЗначений = Новый СписокЗначений;
Пока Выборка.Следующий() Цикл
СписокЗначений.Добавить(Выборка.Ссылка, Выборка.Наименование);
КонецЦикла;
Мы передаем сформированный СписокЗначений нашей внешней компоненте. ВК берет на себя задачу отрисовки этого списка в виде всплывающего окна под полем ввода. Ключевой момент здесь: ВК делает это таким образом, что фокус ввода остается в нашем основном текстовом поле.
При каждом последующем изменении текста в поле ввода, мы повторяем шаги 3 и 4, динамически обновляя содержимое и, возможно, позицию нашего кастомного списка.
Внешняя компонента также должна предоставлять механизм для обработки выбора элемента пользователем. Это может быть событие, которое возникает при нажатии Enter на выделенном элементе в списке или при клике мышью. В этом событии мы получаем выбранное значение и заполняем им наше основное поле ввода.
Когда пользователь выбирает значение, или нажимает Esc, или поле ввода теряет фокус, наша ВК должна закрыть выпадающий список.
Мы видим, что это достаточно комплексная задача для обычных форм. Использование внешней компоненты значительно упрощает её решение, предоставляя необходимую гибкость и контроль над элементами интерфейса, что невозможно достичь стандартными средствами платформы 1С v8.3 для обычных форм. Мы всегда должны помнить об архитектурных ограничениях платформы при постановке таких задач и искать оптимальные пути их обхода.